// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

/**
 * @file
 *
 * AST nodes mainly includes three kinds of nodes: Decl, Expr and Type. And we keep as much source code information as
 * possible, so it's easy to convert AST back to source code.
 */

#ifndef CANGJIE_AST_NODE_H
#define CANGJIE_AST_NODE_H

#include <bitset>
#include <limits>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <variant>
#include <vector>

#include "cangjie/AST/AttributePack.h"
#include "cangjie/AST/Comment.h"
#include "cangjie/AST/Identifier.h"
#include "cangjie/AST/IntLiteral.h"
#include "cangjie/AST/Types.h"
#include "cangjie/Basic/Linkage.h"
#include "cangjie/Basic/Position.h"
#include "cangjie/Lex/Token.h"
#include "cangjie/Utils/CheckUtils.h"
#include "cangjie/Utils/ConstantsUtils.h"

namespace Cangjie {
enum class ScopeKind : uint8_t;
enum class ExprKind : uint8_t;

namespace AST {
struct Symbol;
struct Expr;
struct FuncArg;
struct Decl;
struct FuncDecl;
struct StructDecl;
struct CallExpr;
struct ArrayLit;
struct RefExpr;
struct NameReferenceExpr;
struct Pattern;
struct Package;
struct File;
struct LitConstExpr;
struct Block;
struct PropDecl;
struct MacroInvocation;
struct LambdaExpr;
enum class BuiltInType : uint8_t;

using TyVar = GenericsTy;
using TyVarEnv = std::map<Ptr<TyVar>, std::set<Ptr<Ty>>>;

/**
 * ASTKind of the Node.
 */
enum class ASTKind : uint8_t {
#define ASTKIND(KIND, VALUE, NODE, SIZE) KIND,
#include "cangjie/AST/ASTKind.inc"
#undef ASTKIND
};

/**
 * Mapping of ASTKind to string.
 */
const static std::unordered_map<ASTKind, std::string> ASTKIND_TO_STR = {
#define ASTKIND(KIND, VALUE, NODE, SIZE) {ASTKind::KIND, VALUE},
#include "cangjie/AST/ASTKind.inc"
#undef ASTKIND
};

/**
 * ForInKind of the ForInExpr.
 */
enum class ForInKind : uint8_t {
    FORIN_INVALID,
    FORIN_RANGE,
    FORIN_STRING,
    FORIN_ITER
};

// Used to convert unique_ptr vector to pointer vector.
template <typename T> std::vector<Ptr<T>> ConverVector(const std::vector<OwnedPtr<T>>& source)
{
    std::vector<Ptr<T>> result;
    auto convertPtr = [&result](const OwnedPtr<T>& ptr) { result.push_back(ptr.get()); };
    std::for_each(source.begin(), source.end(), convertPtr);
    return result;
}

/**
 * Base struct for all nodes of the abstract syntax tree. All nodes contain position information marking the beginning
 * of the corresponding source text segment.
 */
struct Node {
    Position begin; /**< The begin Position of the Node. Generated by parser */
    Position end;   /**< The end Position of the Node. Generated by parser */

    CommentGroups comments; /**< Comments attached to the node. Generated by parser */
    /**
     * The semantic type of the Node.
     * W: ASTContext, Clone, Create, Expand, CodeGenHLIR (PrepareImportedAST), ASTSerialization (Load),
     * FFTSerialization, Sema.
     * R: Clone, Create, Expand, PrintNode, CodeGenCHIR, CodeGenHLIR, CodeGenLLVM, ASTSerialization
     * (Save) FFTSerialization, Sema, Mangle, Utils/Utils.
     * Problems: CodeGenHLIR etc should not write this field.
     * */
    Ptr<Ty> ty{Ty::GetInitialTy()};
    /**
     * The Symbol of the Node.
     * W: Collector.
     * R: ASTContext, Assumption, CheckInitialization, Search, TypeChecker (few).
     * Problems: Why do we even need Symbol?
     */
    Symbol* symbol{nullptr};
    /**
     * Managed by ScopeManager.
     * W: Create, Collector, Desugar.
     * R: PreCheck, ScopeManager, AST2CHIR, Assumption, TypeChecker, CheckInitialization (Sema), CodeGenHLIR,
     * CheckTypeCompatible, Collector, Desugar, PrintNode.
     */
    std::string scopeName{""};
    /**
     * Id used for export and import, should be unique value for each decl in single package.
     * NOTE: For cjo's compatibility of different version, the exportId must be decl's signature.
     * W: Utils/Mangle.cpp, ASTSerialization
     * R: ASTSerialization
     */
    std::string exportId{""};
    /** Current file node.
     * W: Desugar, Create, CompilerStrategy, ASTSerialization, MacroExpansion, Parse, Collector, TypeChecker.
     * R: Desugar, PreCheck, Create, CodeGenHLIR, CompilerStrategy, ImportManager, Collector, TypeChecker.
     * Problems: Why so many modules write this field?
     * Generated by parser
     */
    Ptr<File> curFile{nullptr};
    /**
     * Current macro call node.
     * W: MacroExpansion.
     * R: TypeChecker, Collector.
     */
    Ptr<Node> curMacroCall{nullptr};
    /**
     * Scope level, import scope is 0, each file has separate import scope. Package's toplevel scope is 1.
     * W: Collector, Create, Desugar.
     * R: TypeChecker, Create, ScopeManager, AST2CHIR, PreCheck, Sema.
     */
    uint32_t scopeLevel{0};
    /**
     * A flag set by Walker, indicating this node is visited by walker.
     * W: Walker.
     * R: Walker.
     */
    mutable unsigned visitedByWalkerID{0};

    /**
     * A flag set by Walker, indicating this node is in macrocall for lsp.
     * W: Sema.
     * R: Searcher, DiagnosticEngine.
     */
    bool isInMacroCall{false};

    /**
     * W: On construction.
     * R: AST2CHIR, All CodeGen, Macro, Serialization, ImportManager, Parse, Sema
     * Generated by parser
     * NOTE: This must be const, cannot be modified outside constructor.
     */
    const ASTKind astKind;
    Node() : astKind(ASTKind::NODE)
    {
    }
    virtual ~Node();
    virtual std::string ToString() const
    {
        return "";
    }

    /**
     * Get the @p attr.
     */
    const AttributePack GetAttrs() const
    {
        return attributes;
    }

    void CopyAttrs(const AttributePack& attrs)
    {
        attributes = attrs;
    }

    void CloneAttrs(const Node& other)
    {
        attributes = other.attributes;
    }

    /**
     * Set the attributes in @p attrs to @c true.
     */
    template <typename... Args> void EnableAttr(Args... attrs) noexcept
    {
        (attributes.SetAttr(attrs, true), ...);
    }

    /**
     * Set the attributes in @p attrs to @c false.
     */
    template <typename... Args> void DisableAttr(Args... attrs) noexcept
    {
        (attributes.SetAttr(attrs, false), ...);
    }

    /**
     * Check whether the @p attr is @c true.
     */
    bool TestAttr(Attribute attr) const noexcept
    {
        return attributes.TestAttr(attr);
    }

    /* Check whether all given attributes are enabled. */
    template <typename... Args> bool TestAttr(Attribute attr, Args&&... args) const noexcept
    {
        return TestAttr(attr) && TestAttr(std::forward<Args>(args)...);
    }

    /* Check whether any of the given attributes is enabled. */
    template <typename... Args> bool TestAnyAttr(Attribute attr, Args&&... args) const noexcept
    {
        bool ret = TestAttr(attr);
        if constexpr (sizeof...(args) != 0) {
            ret = ret || TestAnyAttr(std::forward<Args>(args)...);
        }
        return ret;
    }

    /**
     * Remove some compiler added information.
     */
    virtual void Clear() noexcept
    {
        DisableAttr(Attribute::INITIALIZED);
        DisableAttr(Attribute::INITIALIZATION_CHECKED);
        DisableAttr(Attribute::IS_CHECK_VISITED);
        ty = Ty::GetInitialTy();
    }

    bool IsStructOrClassDecl() const noexcept
    {
        return astKind == ASTKind::CLASS_DECL || astKind == ASTKind::STRUCT_DECL;
    }

    /**
     * Whether a declaration is a struct declaration.
     */
    bool IsNominalDecl() const noexcept
    {
        return astKind == ASTKind::CLASS_DECL || astKind == ASTKind::INTERFACE_DECL ||
            astKind == ASTKind::STRUCT_DECL || astKind == ASTKind::EXTEND_DECL || astKind == ASTKind::ENUM_DECL;
    }
    /**
     * Whether a node is ClassBody, InterfaceBody, StructBody or DummyBody for 'extend' and 'enum'.
     */
    bool IsNominalDeclBody() const noexcept
    {
        return astKind == ASTKind::CLASS_BODY || astKind == ASTKind::INTERFACE_BODY ||
            astKind == ASTKind::STRUCT_BODY || astKind == ASTKind::DUMMY_BODY;
    }

    /**
     * Whether a declaration is ClassDecl or InterfaceDecl.
     */
    bool IsClassLikeDecl() const noexcept
    {
        return astKind == ASTKind::CLASS_DECL || astKind == ASTKind::INTERFACE_DECL;
    }

    /**
     * Whether a node is ClassBody or InterfaceBody.
     */
    bool IsClassLikeDeclBody() const noexcept
    {
        return astKind == ASTKind::CLASS_BODY || astKind == ASTKind::INTERFACE_BODY;
    }

    /**
     * Whether the Node is FuncDecl or LambdaExpr.
     */
    bool IsFuncLike() const noexcept
    {
        return astKind == ASTKind::FUNC_DECL || astKind == ASTKind::LAMBDA_EXPR ||
            astKind == ASTKind::PRIMARY_CTOR_DECL || astKind == ASTKind::MACRO_DECL;
    }

    /**
     * Whether the Node is FuncDecl or LambdaExpr.
     */
    bool IsFunc() const noexcept
    {
        return astKind == ASTKind::FUNC_DECL;
    }

    /**
     * Whether a node is function or PropDecl.
     */
    bool IsFuncOrProp() const noexcept
    {
        return astKind == ASTKind::FUNC_DECL || astKind == ASTKind::PROP_DECL;
    }

    /**
     * Whether a node is Decl.
     */
    bool IsDecl() const noexcept
    {
        return astKind >= ASTKind::DECL && astKind <= ASTKind::INVALID_DECL;
    }

    /**
     * Whether a node is Expr.
     */
    bool IsExpr() const noexcept
    {
        return astKind >= ASTKind::EXPR && astKind <= ASTKind::INVALID_EXPR;
    }

    /**
     * Whether the Node is Invalid Expr or Invalid Decl.
     */
    bool IsInvalid() const noexcept
    {
        return astKind == ASTKind::INVALID_DECL || astKind == ASTKind::INVALID_EXPR || astKind == ASTKind::INVALID_TYPE;
    }

    /**
     * Whether the Node is a loop expr.
     */
    bool IsLoopExpr() const noexcept
    {
        return astKind == ASTKind::FOR_IN_EXPR || astKind == ASTKind::WHILE_EXPR || astKind == ASTKind::DO_WHILE_EXPR;
    }
    /**
     * Whether a declaration is static or global.
     * @return true if a declaration is either static or global.
     */
    bool IsStaticOrGlobal() const noexcept
    {
        return this->TestAttr(Attribute::GLOBAL) || this->TestAttr(Attribute::STATIC);
    }

    bool IsTypeDecl() const noexcept
    {
        return astKind == ASTKind::CLASS_DECL || astKind == ASTKind::INTERFACE_DECL ||
            astKind == ASTKind::STRUCT_DECL || astKind == ASTKind::ENUM_DECL || astKind == ASTKind::TYPE_ALIAS_DECL ||
            astKind == ASTKind::GENERIC_PARAM_DECL || astKind == ASTKind::BUILTIN_DECL;
    }

    /**
     * Whether the Node is Macro Expand Node.
     */
    bool IsMacroCallNode() const noexcept
    {
        return astKind == ASTKind::MACRO_EXPAND_DECL || astKind == ASTKind::MACRO_EXPAND_EXPR ||
            astKind == ASTKind::MACRO_EXPAND_PARAM;
    }

    /**
     * Whether the node has open semantics.
     * That is, it is a open class or interface, or an open/abstract func.
     * The behaviour is UNDEFINED if the node is invalid.
     */
    virtual bool IsOpen() const noexcept { return false; }

    /**
     * Should diagnostic engine emit a diagnose message for this node.
     * Common usage: Diagnose(node.ShouldDiagnose(), ...)
     * @param allowCompilerAdd if true, do not check whether this is node is added by the compiler
     * @return false if this->TestAttr(Attribute::COMPILER_ADD) or at least one child's ty is invalid, true otherwise
     */
    bool ShouldDiagnose(bool allowCompilerAdd = false) const;

    /**
     * Check @p other node is in same package.
     */
    bool IsSamePackage(const Node& other) const;

    /**
     * Get node's targets decl.
     */
    std::vector<Ptr<Decl>> GetTargets() const;
    /**
     * Get node's target decl.
     */
    Ptr<Decl> GetTarget() const;
    /**
     * Set node's target decl.
     */
    void SetTarget(Ptr<Decl> target);

    /**
     * Get a MacroInvocation ptr.
     * @return MacroInvocation ptr if a node is MacroExpandExpr or MacroExpandDecl,
     *  nullptr otherwise.
     */
    Ptr<const MacroInvocation> GetConstInvocation() const;

    /**
     * Get a MacroInvocation ptr.
     * @return MacroInvocation ptr if a node is MacroExpandExpr or MacroExpandDecl,
     *  nullptr otherwise.
     */
    Ptr<MacroInvocation> GetInvocation();

    /**
     * Get the begin Position of the Node.
     * @return begin Position in macrocall file if the Node is expanded from macrocall,
     *  begin position in curfile otherwise.
     */
    Position GetBegin() const;

    /**
     * Get the end Position of the Node.
     * @return end Position in macrocall file if the Node is expanded from macrocall,
     *  end position in curfile otherwise.
     */
    Position GetEnd() const;

    /**
     * Get the sourcePos of macrocall by originPos in curfile.
     * @return the sourcePos in macrocall file if the Node is expanded from macrocall,
     *  originPos in curfile otherwise.
     */
    Position GetMacroCallPos(Position originPos, bool isLowerBound = false) const;

    /**
     * Get the new Position of macrocall in curfile by originPos before the macro is expanded, for lsp.
     * @return new Position of macrocall in curfile if the Node is MacroExpandExpr/MacroExpandDecl or in macrocall,
     *  INVALID_POSITION otherwise.
     */
    Position GetMacroCallNewPos(const Position& originPos);

    /**
     * For debug,
     * get the original Position of the node if it is from MacroCall in curfile,
     * curPos otherwise.
     */
    Position GetDebugPos(const Position& curPos) const;

    const std::string& GetFullPackageName() const;

protected:
    explicit Node(ASTKind kind) : astKind(kind)
    {
    }

private:
    AttributePack attributes;
};

/**
 * normal string, JString, multiple lines, or multiple lines of string.
 */
enum class StringKind { NORMAL, JSTRING, MULTILINE, MULTILINE_RAW };

/**
 * Expression has suffix '?' or not.
 */
enum class SuffixKind { NONE, QUEST };

/**
 * Access control modifiers
 */
struct Modifier : Node {
    TokenKind modifier; /**< Modifier token. */
    bool isExplicit = false;
    Modifier(TokenKind kind, const Position& pos) : Node(ASTKind::MODIFIER), modifier(kind)
    {
        begin = pos;
        end = {pos.fileID, pos.line, pos.column + Len(kind)};
        isExplicit = true;
    }
    bool operator<(const Modifier& rhs) const
    {
        return (modifier < rhs.modifier);
    }
    std::string ToString() const override;
};

enum class AnnotationKind {
    JAVA,
    CALLING_CONV,
    C,
    JAVA_MIRROR,
    JAVA_IMPL,
    OBJ_C_MIRROR,
    OBJ_C_IMPL,
    FOREIGN_NAME,
    ATTRIBUTE,
    /**
     * NOTE: 'OVERFLOW' is a macro in early versions of glibc (VERSION < 2.27).
     * To be compatiable with old versions of glibc we should avoid using 'OVERFLOW' as an identifier.
     * For details, please check 'https://man7.org/linux/man-pages/man3/matherr.3.html'.
     */
    NUMERIC_OVERFLOW,
    INTRINSIC,
    WHEN,
    FASTNATIVE,
    ANNOTATION, // Indicate @Annotation.
    CUSTOM,     // Indicate a Custom Annotation, such as @JsonName.
    CONSTSAFE,
    DEPRECATED,
    FROZEN,
    ENSURE_PREPARED_TO_MOCK,
    UNKNOWN
};

using AnnotationTargetT = uint16_t;
/**
 * Target of `@Annotation`.
 */
enum class AnnotationTarget : AnnotationTargetT {
    TYPE = 0,
    PARAMETER,
    INIT,
    MEMBER_PROPERTY,
    MEMBER_FUNCTION,
    MEMBER_VARIABLE,
    ENUM_CONSTRUCTOR,
    GLOBAL_FUNCTION,
    GLOBAL_VARIABLE,
    EXTEND,
};

/**
 * Built-in or custom Annotation.
 */
struct Annotation : public Node {
    bool isCompileTimeVisible{};                             /**< True when @! Annotation. */
    AnnotationKind kind;                                     /**< Generated by parser */
    Identifier identifier;                                   /**< Generated by parser */
    Position lsquarePos;
    std::vector<OwnedPtr<FuncArg>> args;                     /**< Arguments in order. Generated by parser */
    Position rsquarePos;
    OverflowStrategy overflowStrategy{OverflowStrategy::NA}; /**< Generated by parser */
    Identifier adAnnotation;                                 /**< Generated by parser, Optional, consider delete */
    std::vector<Token> attrs;                                /**< attributes for @Attribute, Generated by parser. */
    std::vector<Position> attrCommas;                        /**< commas between attributes, Generated by parser. */
    // For j-foreign inter operation.
    std::string definedPackage; /**< Generated by parser, Optional */
    // For When Annotations.
    OwnedPtr<Expr> condExpr; /**< Generated by parser, Optional */
    // For @Annotation.
    uint16_t target = 0;
    // For imported j-foreign annotations.
    // It is true only if the annotation is defined with `@Retention(RetentionPolicy.RUNTIME)`.
    bool runtimeVisible = false;
    // For Custom Annotation.
    OwnedPtr<Expr> baseExpr; /**< Generated by parser after macro */
    Annotation(const std::string& name, AnnotationKind annoKind, const Position& pos)
        : Node(ASTKind::ANNOTATION), kind(annoKind), identifier{name, INVALID_POSITION, INVALID_POSITION}
    {
        begin = pos;
    }
    Annotation() : Node(ASTKind::ANNOTATION)
    {
    }

    bool TestTarget(AnnotationTarget t) const noexcept
    {
        CJC_ASSERT(static_cast<uint64_t>(t) <
            static_cast<uint64_t>(std::numeric_limits<std::underlying_type_t<AnnotationTarget>>::digits));
        return static_cast<bool>(target & (static_cast<AnnotationTargetT>(1) << static_cast<AnnotationTargetT>(t)));
    }

    void EnableTarget(AnnotationTarget t) noexcept
    {
        CJC_ASSERT(static_cast<uint64_t>(t) <
            static_cast<uint64_t>(std::numeric_limits<std::underlying_type_t<AnnotationTarget>>::digits));
        target |= static_cast<AnnotationTargetT>(
            static_cast<AnnotationTargetT>(1) << static_cast<AnnotationTargetT>(t));
    }

    void EnableAllTargets() noexcept
    {
        target = static_cast<AnnotationTargetT>(~0u);
    }

    bool operator<(const Annotation& rhs) const
    {
        return (kind < rhs.kind);
    }
};

/**
 * Reference represent a map of identifier and target, which is determined by sema.
 */
struct Reference {
    /**< Reference's name. (When it's text is raw identifier the raw mark "``" will be removed.
     * e.g., name of "`type_1`" is "type_1".) Generated by Parser. */
    SrcIdentifier identifier;
    Ptr<Decl> target{nullptr};      /**< Target of the Reference. */
    std::vector<Ptr<Decl>> targets; /**< Overloaded Functions or super class/interfaces. */
    Reference() = default;
    explicit Reference(const SrcIdentifier& id) : identifier{id}
    {
    }
    explicit Reference(SrcIdentifier&& id) : identifier{std::move(id)}
    {
    }

    explicit Reference(const std::string& name) : identifier{name, INVALID_POSITION, INVALID_POSITION, false}
    {
    }
};

/**
 * Base type node.
 */
struct Type : Node {
    ~Type() override = default;
    Position commaPos;  /**< Generated by parser, Optional */
    Position bitAndPos; /**< Generated by parser, Optional */

    // The following three properties are used for type parameters,
    // e.g in a tuple type "(p1:Int64, `p2`:Int64)"
    // "p1" and "p2" is typeParameterName
    // "`p2`" typeParameterName is "p2" generated by raw identifier
    // colonPos is the position of `:`
    // typePos is the position of `Int64`
    Position colonPos; /**< Generated by parser, Optional */
    Position typePos;  /**< Generated by parser, Optional */

    /**< TypeParameter's name. (When it's raw identifier the raw mark "``" will be removed.
     * e.g., name of "`type_1`" is "type_1".) Generated by parser. */
    std::string typeParameterName; /**< Generated by parser, Optional */
    /**< If typeParameter's name text is raw identifer, it's name text is composed of an ordinary identifier or
     * a keyword wrapped by a pair of backquotes. e.g.,"`type_1`". Generated by parser. */
    bool typeParameterNameIsRawId{false};

    Type() : Node(ASTKind::TYPE)
    {
    }
    void Clear() noexcept override
    {
        Node::Clear();
    }
    virtual std::vector<Ptr<Type>> GetTypeArgs() const
    {
        return {};
    }
    std::string GetTypeParameterNameRawText() const
    {
        return typeParameterNameIsRawId ? ("`" + typeParameterName + "`") : typeParameterName;
    }

protected:
    Type(ASTKind kind) : Node(kind)
    {
    }
};

/**
 * Bad type node emitted on parse errors.
 */
struct InvalidType : Type {
    explicit InvalidType(const Position& pos) : Type(ASTKind::INVALID_TYPE)
    {
        EnableAttr(Attribute::IS_BROKEN);
        begin = pos;
        end = pos;
    }
};

/**
 * Represents a reference type.
 */
struct RefType : Type {
    Reference ref;                             /**< Reference of the type. */
    Position leftAnglePos;                     /**< Position of '<'. */
    std::vector<OwnedPtr<Type>> typeArguments; /**< Instantiation type. */
    Position rightAnglePos;                    /**< Position of '>'. */
    RefType() : Type(ASTKind::REF_TYPE)
    {
    }
    void Clear() noexcept override
    {
        Type::Clear();
        ref.target = nullptr;
        ref.targets.clear();
    }
    std::string ToString() const override;
    std::vector<Ptr<Type>> GetTypeArgs() const override
    {
        return ConverVector(typeArguments);
    }
    /**
     * Check if type target is generic ThisType.
     */
    bool IsGenericThisType() const;
};

/**
 * Represents This type.
 */
struct ThisType : Type {
    explicit ThisType(const Position& pos) : Type(ASTKind::THIS_TYPE)
    {
        begin = pos;
        end = begin;
        end.column += Len(TokenKind::THISTYPE);
    }
};

/**
 * Represents primitive type, including Rune, bool, Int32, etc.
 */
struct PrimitiveType : Type {
    std::string str;                       /**< Primitive type string represents. */
    TypeKind kind{TypeKind::TYPE_INVALID}; /**< TYPE_INT8, TYPE_INT16, etc. */
    PrimitiveType() : Type(ASTKind::PRIMITIVE_TYPE)
    {
    }
    std::string ToString() const override
    {
        return str;
    }
};

/**
 * Represents a parenthesized type which is used for type conversion.
 */
struct ParenType : Type {
    Position leftParenPos;  /**< Position of '('. */
    OwnedPtr<Type> type;    /**< Type between '(' and ')'. */
    Position rightParenPos; /**< Position of ')'. */
    ParenType() : Type(ASTKind::PAREN_TYPE)
    {
    }
};

/**
 * Represents a Nested Type with scope like obja.objb.c, @p baseType is obja.objb, @p field is c.
 */
struct QualifiedType : Type {
    OwnedPtr<Type> baseType; /**< Split from last '.', take the left parts. Generated by parser*/
    Position dotPos;         /**< Position of the '.'. Generated by parser*/
    /**< Split from last '.', take the right parts. When it's text raw identifier the raw mark "``" will be removed.
     * e.g., name of "`type_1`" is "type_1".) Generated by parser */
    SrcIdentifier field;
    Position leftAnglePos;                     /**< Position of '<' Generated by parser,Optional*/
    std::vector<OwnedPtr<Type>> typeArguments; /**< Instantiation type. Generated by parser,Optional*/
    Position rightAnglePos;                    /**< Position of '>' Generated by parser,Optional*/
    Ptr<Decl> target{nullptr};                 /**< Target of the QualifiedType. */
    QualifiedType() : Type(ASTKind::QUALIFIED_TYPE)
    {
    }
    void Clear() noexcept override
    {
        Type::Clear();
        target = nullptr;
    }

    std::vector<Ptr<Type>> GetTypeArgs() const override
    {
        return ConverVector(typeArguments);
    }
    /**
     * Get the field Position of the QualifiedType.
     * @return field Position in macrocall file if the QualifiedType is expanded from macrocall,
     *  field position in curfile otherwise.
     */
    Position GetFieldPos() const;
};

/**
 * A OptionType node represents the syntactic sugar of an option type, example: `?T` represents Option<T>.
 */
struct OptionType : Type {
    OwnedPtr<Type> componentType;      /**< The component type of the option type. Generated by parser*/
    unsigned int questNum{0};          /**< Number of the quest. Generated by parser*/
    std::vector<Position> questVector; /**< Positions of '?'. Generated by parser*/
    OwnedPtr<RefType> desugarType;     /**< Desugar type of '?T'. */
    OptionType() : Type(ASTKind::OPTION_TYPE)
    {
    }
};

/**
 * A ConstantType node represents the constant value start with '$' in generic parameter list.
 * Currently, this type is used only in VArrayType.
 */
struct ConstantType : public Type {
    OwnedPtr<Expr> constantExpr; /**< Expression after the '$'. */
    Position dollarPos;          /**< Positions of '$'. */
    ConstantType() : Type(ASTKind::CONSTANT_TYPE)
    {
    }
};

/**
 * Represents an VArray Type. 'begin' is also the position of 'VArray'.
 */
struct VArrayType : public Type {
    Position varrayPos;          /**< Positions of 'VArray'. */
    Position leftAnglePos;       /**< Positions of '<'. */
    OwnedPtr<Type> typeArgument; /**< The component type of the array. */
    OwnedPtr<Type> constantType; /**< ConstantType */
    Position rightAnglePos;      /**< Positions of '>'. */
    VArrayType() : Type(ASTKind::VARRAY_TYPE)
    {
    }
};
/**
 * A FuncType node represents a function type, example: `(Int32, Int32)->Int32`, @p paramType is (Int32, Int32), @p
 * retType is Int32.
 */
struct FuncType : Type {
    Position leftParenPos;                  /**< Position of '('. */
    std::vector<OwnedPtr<Type>> paramTypes; /**< Splitted by comma, type(s) of parameter(s) */
    Position rightParenPos;                 /**< Position of ')'. */
    Position arrowPos;                      /**< Position of '->'. */
    OwnedPtr<Type> retType;                 /**< Split from last "->", take the right parts. */
    FuncType() : Type(ASTKind::FUNC_TYPE)
    {
    }
    bool isC{false};
};

/**
 * A TupleType node represents a tuple type defined by type*type*type.
 */
struct TupleType : Type {
    Position leftParenPos;                  /**< Position of '('. Generated by parser */
    Position rightParenPos;                 /**< Position of ')'. Generated by parser*/
    std::vector<OwnedPtr<Type>> fieldTypes; /**< Type of each filed in tuple. Generated by parser*/
    std::vector<Position> commaPosVector;   /**< Positions of ','. Generated by parser*/
    TupleType() : Type(ASTKind::TUPLE_TYPE)
    {
    }
};

/**
 * The inheritance node has been visited or under visiting.
 */
enum class InheritanceVisitStatus {
    UNVISITED, /**< Not visit yet. */
    VISITING,  /**< Visiting now. */
    VISITED,   /**< Has been visited. */
};

/**
 * Represents Generic Constraint.
 */
struct GenericConstraint : public Node {
    Position wherePos;                       /**< The position of where. */
    OwnedPtr<RefType> type;                  /**< Type variable. */
    Position operatorPos;                    /**< The position of upper bound operator. */
    std::vector<Position> bitAndPos;         /**< The position of '&'. */
    std::vector<OwnedPtr<Type>> upperBounds; /**< Upper bounds, class, interface */
    Position commaPos;                       /**< The position of where. */
    GenericConstraint() : Node(ASTKind::GENERIC_CONSTRAINT)
    {
    }
};

/**
 * Represents Generic.
 */
struct Generic : public Node {
    Position leftAnglePos;                                       /**< The position of left angle bracket. */
    std::vector<OwnedPtr<GenericParamDecl>> typeParameters;      /**< Generic type parameters. */
    Position rightAnglePos;                                      /**< The position of right angle bracket. */
    std::vector<OwnedPtr<GenericConstraint>> genericConstraints; /**< Constraints of type parameters. */
    TyVarEnv assumptionCollection;
    Generic() : Node(ASTKind::GENERIC)
    {
    }
};

struct DeclHash {
    size_t instVar{0}; /**< Hash of type declaration's data layout (instantce member variables). */
    size_t virt{0};    /**< Hash of member's which allowing dynamic dispatch (virtual functions and properties). */
    size_t sig{0};     /**< the API of a decl (e.g. name of named parameter). Need recompile user*/
    size_t srcUse{0};  /**< the ABI (e.g. foreign, @Annotation) and source usage of a decl (e.g. public). */
    size_t bodyHash{0};    /**< Change of this part does not propagate to users. */
    int gvid{0}; /** GlobalVarOrder. no file here as it is stored in Decl*/
};

/**
 * Base decl node.
 */
struct Decl : Node {
    std::set<Modifier> modifiers;                  /**< Modifier set of the Decl. Generated by parser */
    std::vector<OwnedPtr<Annotation>> annotations; /**< Annotation set of the Decl. Generated by parser */
    OwnedPtr<ArrayLit> annotationsArray;           /**< Custom annotations of the Decl. Generated by Sema. */
    /**< Decl's name. (When it's text is raw identifier, the raw mark "``" will be removed.
     * e.g., name of "`type_1`" is "type_1".) Generated by parser. */
    SrcIdentifier identifier;
    OwnedPtr<Generic> generic;    /**< Generated by parser , Optional */
    std::string identifierForLsp; /**< Decl's raw name, identifier is changed such as PropDecl. */
    Position keywordPos;          /**< Position of the keyword, like var, func, etc. Generated by parser */
    std::string rawMangleName;    // mangle name generated by parser, used by incremental compile

    // hash values, used by incremental compile
    DeclHash hash{};
    bool toBeCompiled{false};
    /** The name after mangling.
     * W: AST2CHIR, CodeGenHLIR, CodeGenJS, CodeGenLLVM, ASTSerialization, Utils.Mangle,
     * Parser.CheckRenameAnnotationKind
     * R: AST2CHIR, CodeGenHLIR, CodeGenJS, CodeGenLLVM, ASTSerialization, Utils.Mangle
     */
    std::string mangledName;
    std::string moduleName;             /**< The root package name of current package. */
    std::string fullPackageName;        /**< The full package name of current package. */
    Ptr<Decl> outerDecl{nullptr};       /**< Pointer to current outer declaration. Generated by parser */
    Ptr<Decl> genericDecl{nullptr};     /**< Pointer to generic declaration if it is an instantiated one. */
    Linkage linkage{Linkage::EXTERNAL}; /**< The linkage of a decl. Default: external */
    bool doNotExport{false};            /**< If the flag is true, the Decl will not be exported. */
    Ptr<Decl> platformImplementation;
    mutable std::vector<Ptr<const Decl>> dependencies; /**< Variables that the current one depends on */

    Decl() : Node(ASTKind::DECL)
    {
    }
    ~Decl() override = default;

    InheritanceVisitStatus checkFlag{InheritanceVisitStatus::UNVISITED};

    unsigned captureIndex = 0; /**< The index in the function context class. */

    /**
     * Whether a declaration is a member declaration.
     */
    bool IsMemberDecl() const noexcept
    {
        return outerDecl && outerDecl->IsNominalDecl();
    }

    /**
     * Check whether contains the @p anno.
     */
    bool HasAnno(AnnotationKind anno) const
    {
        for (auto& it : annotations) {
            if (it->kind == anno)
                return true;
        }
        return false;
    }

    void Clear() noexcept override
    {
        checkFlag = InheritanceVisitStatus::UNVISITED;
        Node::Clear();
    }
    virtual std::vector<OwnedPtr<Decl>>& GetMemberDecls()
    {
        static std::vector<OwnedPtr<Decl>> empty;
        return empty;
    };
    const std::vector<OwnedPtr<Decl>>& GetMemberDecls() const
    {
        return const_cast<Decl*>(this)->GetMemberDecls();
    };

    std::vector<Ptr<Decl>> GetMemberDeclPtrs() const;
    bool IsBuiltIn() const;
    /**
     * Get a generic decl's generic declaration.
     */
    Ptr<Generic> GetGeneric() const;
    /**
     * Get the identifier Position of the Decl.
     * @return identifier Position in macrocall file if the Decl is expanded from macrocall,
     *  identifier position in curfile otherwise.
     */
    Position GetIdentifierPos() const;

    /**
     * Check if a declaration can be exported.
     * @return true if declaration can be exported.
     */
    virtual bool IsExportedDecl() const;

    /**
     * Check if a declaration is marked with 'const'.
     * @return true if the declaration is marked with 'const'.
     */
    bool IsConst() const;

    /**
     * Get the desugar decl of this decl
     * @return the ptr of desugar decl if it exist, nullptr otherwise.
     */
    Ptr<FuncDecl> GetDesugarDecl() const;

    bool IsCommonOrPlatform() const;

    bool IsCommonMatchedWithPlatform() const;

protected:
    Decl(ASTKind kind) : Node(kind)
    {
    }
};

struct InheritableDecl : public Decl {
    Position upperBoundPos;                     /**< Position of <:. */
    std::vector<OwnedPtr<Type>> inheritedTypes; /**< Super class or super interfaces. */
    std::set<Ptr<InterfaceTy>> GetSuperInterfaceTys() const;
    std::vector<Ptr<InterfaceTy>> GetStableSuperInterfaceTys() const;
    // guarantees sub-types always exist before super-types
    std::vector<Ptr<AST::ClassLikeDecl>> GetAllSuperDecls();

protected:
    InheritableDecl(ASTKind kind) : Decl(kind)
    {
    }
};

enum class BuiltInType : uint8_t {
    ARRAY,
    POINTER,
    CSTRING,
    CFUNC,
    VARRAY,
    // Will have other builtin types.
};

/**
 * Built-in decl is for built-in types, such as Array, CString.
 */
struct BuiltInDecl : public Decl {
    BuiltInType type;
    BuiltInDecl(BuiltInType type) : Decl(ASTKind::BUILTIN_DECL), type(type)
    {
    }
    bool IsType(BuiltInType ty) const
    {
        return ty == type;
    }
};

/**
 * A GenericParamDecl node represents a generic type decl in generic function, class, interface.
 */
struct GenericParamDecl : public Decl {
    Position commaPos; /**< The comma position of generic parameters. Generated by parser, Optional */
    GenericParamDecl() : Decl(ASTKind::GENERIC_PARAM_DECL)
    {
    }
};

struct VarDeclAbstract : Decl {
    OwnedPtr<Type> type;        /**< Generated by parser */
    Position colonPos;          /**< Position of ':'. Generated by parser */
    OwnedPtr<Expr> initializer; /**< Initialize Expr. Generated by parser*/
    Position assignPos;         /**< Position of '='. */
    bool isVar{false};          /**< To distinguish @c Let or @c Var. */
    bool isConst{false};        /**< A flag to mark whether the decl is const. Generated by parser */

protected:
    VarDeclAbstract(ASTKind astKind) : Decl(astKind)
    {
    }
};

/**
 * A VarDecl node represents a *local* variable declaration.
 */
struct VarDecl : VarDeclAbstract {
    Ptr<Pattern> parentPattern{nullptr}; /**< Save the target pattern if the varDecl is in pattern. */
    bool isIdentifierCompilerAdd{false}; /**< Is the identifier is add by compiler. */
    bool isResourceVar{false};
    bool isMemberParam{false}; /**< identify member variable parameter. Generated by Parser. LSP will use. */
    VarDecl() : VarDeclAbstract(ASTKind::VAR_DECL)
    {
    }
    std::string ToString() const override;

protected:
    VarDecl(ASTKind kind) : VarDeclAbstract(kind)
    {
    }
};

struct VarWithPatternDecl : VarDeclAbstract {
    OwnedPtr<Pattern> irrefutablePattern; /**< Irrefutable pattern. */
    VarWithPatternDecl() : VarDeclAbstract(ASTKind::VAR_WITH_PATTERN_DECL)
    {
    }
};

/**
 * A parameter to a method or lambda. For most semantic / codegen purposes, a parameter is equivalent to a variable, but
 * its assignment is different from a normal initializer.
 */
struct FuncParam : VarDecl {
    Position notMarkPos;            /**< Position of '!'. Generated by Parser */
    OwnedPtr<Expr> assignment;      /**< Init the param. Generated by Parser */
    Position commaPos;              /**< Position of ','. Generated by Parser */
    OwnedPtr<FuncDecl> desugarDecl; /**< Desugar default param function. */
    bool isNamedParam{false};       /**< identify named parameter. Generated by Parser */
    bool hasLetOrVar{false};        /**< identify 'let' or 'var' in parameter list. Generated by Parser */
    FuncParam() : VarDecl(ASTKind::FUNC_PARAM)
    {
    }
    void Clear() noexcept override
    {
        Decl::Clear();
        DisableAttr(Attribute::HAS_INITIAL);
    }

protected:
    explicit FuncParam(ASTKind astKind) : VarDecl(astKind)
    {
    }
};

/**
 * Empty DummyBody scope for LSP split decl scopes.
 */
struct DummyBody : Node {
    DummyBody() : Node(ASTKind::DUMMY_BODY)
    {
    }
};

/**
 * An EnumDecl node represents an enum declaration.
 */
struct EnumDecl : InheritableDecl {
    /**
     * EnumDecl will be parsed according to the following rules:
     * 1. If there are NO associated values, then constructors in enumBody will be parsed to cases of VarLikeDecl
     * 2. If there are associated values, then constructors in enumBody will be parsed to cases of FuncDecl
     * 3. Members are functions defined in the enum
     */
    Position leftCurlPos;                     /**< The position of '{'. */
    OwnedPtr<DummyBody> bodyScope;            /**< split body scope for LSP. */
    std::vector<OwnedPtr<Decl>> constructors; /**< VarDecl or FuncDecl. */
    std::vector<Position> bitOrPosVector;     /**< Positions of '|'. */
    std::vector<OwnedPtr<Decl>> members;      /**< Functions in the enum. */
    Position rightCurlPos;                    /**< The position of '}'. */
    bool hasArguments{false};                 /**< Has arguments of the constructor, like Identifier1(TypeList1). */
    bool hasEllipsis{false};                  /**< Has ellipsis case, i.e. is non-exhaustive enum. */
    Position ellipsisPos;                     /**< Position of ellipsis, if one exists. */
    EnumDecl() : InheritableDecl(ASTKind::ENUM_DECL)
    {
    }
    std::vector<OwnedPtr<Decl>>& GetMemberDecls() override
    {
        return members;
    }
};

/**
 * A TypeAliasDecl node represents a type declaration.
 */
struct TypeAliasDecl : Decl {
    Position assignPos;  /**< Position of '='. Generated by Parser. */
    OwnedPtr<Type> type; /**< Type of TypeAliasDecl. Generated by Parser. */
    TypeAliasDecl() : Decl(ASTKind::TYPE_ALIAS_DECL)
    {
    }
};

/**
 * A FuncParamList presents a list of params which are in '()'.
 */
struct FuncParamList : Node {
    Position leftParenPos;                     /**< Position of '('. Generated by parser */
    std::vector<OwnedPtr<FuncParam>> params{}; /**< Function parameters. Generated by parser */
    Position rightParenPos;                    /**< Position of ')'. Generated by parser */
    size_t variadicArgIndex{0};                /**< Index of '...'. */
    bool hasVariableLenArg{false};             /**< Whether have variable length argument. */
    FuncParamList() : Node(ASTKind::FUNC_PARAM_LIST)
    {
    }
};

/**
 * Reperesent the Kind of the VARIABLE CAPTURE.
 */
enum class CaptureKind : uint8_t { NO_CAPTURE, CAPTURE_VAR, TRANSITIVE_CAPTURE };

/**
 * A FuncBody node represents a function body which contains @p paramLists, @p retType and @p body.
 */
struct FuncBody : Node {
    std::vector<OwnedPtr<FuncParamList>> paramLists; /**< List of FuncParamList. Generated by parser */
    Position doubleArrowPos;                         /**< Position of '=>'. Generated by parser, Optional  */
    Position colonPos;                               /**< Position of ':'. Generated by parser, Optional */
    OwnedPtr<Type>
        retType; /**< Return type (node) of the function. ret->retType = ParseType(); Generated by parser, Optional */
    OwnedPtr<Block> body;            /**< Body of the function. Generated by parser */
    OwnedPtr<Generic> generic;       /**< Generated by parser, Optional */
    Ptr<FuncDecl> funcDecl{nullptr}; /**< Associated function declaration, should be nil for lambda. */
    std::unordered_set<Ptr<const NameReferenceExpr>> capturedVars; /**< Mutable variables captured by the function. */
    Ptr<FuncBody> outerFunc{nullptr};                              /**< The pointer to the outer function. */
    Ptr<ClassLikeDecl> parentClassLike{nullptr};      /**< Parent Class or Interface. Generated by parser, Optional */
    Ptr<StructDecl> parentStruct{nullptr};            /**< Parent StructDecl. Generated by parser, Optional */
    Ptr<EnumDecl> parentEnum{nullptr};                /**< Parent EnumDecl. Generated by parser, Optional */
    CaptureKind captureKind{CaptureKind::NO_CAPTURE}; /**< Capture Variable Kind. */
    FuncBody() : Node(ASTKind::FUNC_BODY)
    {
    }
    void Clear() noexcept override
    {
        Node::Clear();
        capturedVars.clear();
    }
};

/**
 * Invoke super class's init functions.
 */
enum class ConstructorCall {
    NONE,       /**< No super or other init function being called. */
    OTHER_INIT, /**< Called other init function */
    SUPER       /**< Called super function */
};

/**
 * A FuncDecl node represents a function declaration.
 */
struct FuncDecl : Decl {
    Position leftParenPos;       /**< Position of '('. Generated by parser*/
    Position rightParenPos;      /**< Position of ')'. Generated by parser*/
    OwnedPtr<FuncBody> funcBody; /**< Function body, contains param type and return type. Generated by parser*/

    Ptr<FuncDecl> ownerFunc{nullptr}; /**< For default Parameter, no need to be serialized.*/
    Ptr<PropDecl> propDecl{nullptr};

    OverflowStrategy overflowStrategy{OverflowStrategy::NA};
    ConstructorCall constructorCall{ConstructorCall::NONE}; /**< Super or other init function called in constructor. */
    TokenKind op{TokenKind::ILLEGAL};                       /**< For operator overload. Generated by parser*/
    size_t variadicArgIndex{0};                             /**< Index of '...'. */
    bool hasVariableLenArg{false};     /**< Whether have variable length argument. */
    bool isConst{false};               /**< A flag to mark whether the decl is const. Generated by parser */
    bool isSetter{false};              /**< Whether is setter in PropDecl. Generated by parser */
    bool isGetter{false};              /**< Whether is getter in PropDecl. Generated by parser */
    bool isInline{false};              /**< mark function is an inline function*/
    bool isFastNative{false};          /**< mark function whether has annotation FastNative */
    bool isReExportedOrRenamed{false}; /**< mark function whether is renamed or re-exported. */
    bool isFrozen{false};              /**< mark function whether has annotation Frozen. */
    FuncDecl() : Decl(ASTKind::FUNC_DECL)
    {
    }
    ~FuncDecl() override = default;

    /**
     * Whether a funcDecl is finalizer.
     */
    bool IsFinalizer() const
    {
        return identifier == "~init";
    }

    bool IsExportedDecl() const override;

    bool IsOpen() const noexcept override;
};

/**
 * A MacroDecl node represents a macro declaration.
 */
struct MacroDecl : Decl {
    Position leftParenPos;       /**< Position of '('. */
    Position rightParenPos;      /**< Position of ')'. */
    OwnedPtr<FuncBody> funcBody; /**< Macro body, contains param type and return type. Generated by Parser.*/
    OwnedPtr<FuncDecl> desugarDecl;
    ~MacroDecl() override = default;
    MacroDecl() : Decl(ASTKind::MACRO_DECL)
    {
    }
};

/**
 * A MainDecl node represents Program Entry Point Definition.
 */
struct MainDecl : Decl {
    OwnedPtr<FuncBody> funcBody;    /**< Function body, contains param type and return type. Generated by Parser. */
    OwnedPtr<FuncDecl> desugarDecl; /**< Desugar Main Decl to function. */
    OverflowStrategy overflowStrategy{OverflowStrategy::NA}; /**< Generated by Parser. */
    bool isFastNative{false}; /**< mark decl whether has annotation fastNative, Generated by Parser */
    ~MainDecl() override = default;
    MainDecl() : Decl(ASTKind::MAIN_DECL)
    {
    }
};

struct PrimaryCtorDecl : Decl {
    OwnedPtr<FuncBody> funcBody; /**< Function body, contains param type and return type. Generated by Parser. */
    OverflowStrategy overflowStrategy{OverflowStrategy::NA}; /**< Overflow Strategy of Primary Constructor. */
    bool hasVariableLenArg{false};                           /**< Whether have variable length argument. */
    bool isFastNative{false};                                /**< mark function whether has annotation fastNative */
    bool isConst{false}; /**< A flag to mark whether the decl is const. Generated by parser */
    ~PrimaryCtorDecl() override = default;
    PrimaryCtorDecl() : Decl(ASTKind::PRIMARY_CTOR_DECL)
    {
        // Valid 'PrimaryCtorDecl' must be desugared to 'FuncDecl', 'PrimaryCtorDecl' always not export.
        doNotExport = true;
    }
};

/**
 * A PropDecl node represents a property declaration.
 */
struct PropDecl : VarDecl {
    Position leftCurlPos; /**< The postion of '{'. */
    std::vector<OwnedPtr<FuncDecl>> getters;
    std::vector<OwnedPtr<FuncDecl>> setters;
    Position rightCurlPos; /**< The postion of '}'. */
    ~PropDecl() override = default;
    PropDecl() : VarDecl(ASTKind::PROP_DECL)
    {
    }
    bool IsExportedDecl() const override;

    bool IsOpen() const noexcept override;
};

/**
 * StructBody definition.
 */
struct StructBody : Node {
    Position leftCurlPos;              /**< Position of '{'. */
    std::vector<OwnedPtr<Decl>> decls; /**< Declarations in the body. */
    Position rightCurlPos;             /**< Position of '}'. */
    StructBody() : Node(ASTKind::STRUCT_BODY)
    {
    }
};

/**
 * A StructDecl node represents a struct declaration.
 */
struct StructDecl : InheritableDecl {
    OwnedPtr<StructBody> body; /**< StructBody. */
    bool HasConstOrFrozenInit()
    {
        if (!hasConstOrFrozenInit.has_value()) {
            const auto& decls = body->decls;
            bool has = std::find_if(decls.cbegin(), decls.cend(), [](const OwnedPtr<Decl>& decl) {
                return decl->TestAttr(Attribute::CONSTRUCTOR) &&
                    (decl->IsConst() || decl->HasAnno(AnnotationKind::FROZEN));
            }) != decls.cend();
            hasConstOrFrozenInit = {has};
        }
        return *hasConstOrFrozenInit;
    }

    StructDecl() : InheritableDecl(ASTKind::STRUCT_DECL)
    {
    }
    std::vector<OwnedPtr<Decl>>& GetMemberDecls() override
    {
        return body ? body->decls : Decl::GetMemberDecls();
    }

private:
    std::optional<bool> hasConstOrFrozenInit{std::nullopt};
};

/**
 * InterfaceBody definition.
 */
struct InterfaceBody : Node {
    Position leftCurlPos;              /**< Position of '{'. Generated by Parser. */
    std::vector<OwnedPtr<Decl>> decls; /**< Declarations in the body. Generated by Parser. */
    Position rightCurlPos;             /**< Position of '}'. Generated by Parser. */
    InterfaceBody() : Node(ASTKind::INTERFACE_BODY)
    {
    }
};

/**
 * Common parts of ClassDecl and InterfaceDecl.
 */
struct ClassLikeDecl : InheritableDecl {
    std::set<Ptr<Decl>> subDecls; /**< A <: B ==>  B.subDecls = {A}. */
protected:
    ClassLikeDecl(ASTKind kind) : InheritableDecl(kind)
    {
    }
};

/**
 * An InterfaceDecl node represents an interface declaration.
 */
struct InterfaceDecl : ClassLikeDecl {
    OwnedPtr<InterfaceBody> body; /**< InterfaceBody. Generated by Parser. */
    InterfaceDecl() : ClassLikeDecl(ASTKind::INTERFACE_DECL)
    {
    }
    std::vector<OwnedPtr<Decl>>& GetMemberDecls() override
    {
        return body ? body->decls : Decl::GetMemberDecls();
    }

    bool IsOpen() const noexcept override
    {
        return true;
    }
};

/**
 * ClassBody definition.
 */
struct ClassBody : Node {
    Position leftCurlPos;              /**< Position of '{'. Generated by parser */
    std::vector<OwnedPtr<Decl>> decls; /**< Decls in the body. Generated by parser */
    Position rightCurlPos;             /**< Position of '}'. Generated by parser */
    ClassBody() : Node(ASTKind::CLASS_BODY)
    {
    }
};

/**
 * A CLassDecl node represents a class declaration.
 */
struct ClassDecl : ClassLikeDecl {
    OwnedPtr<ClassBody> body; /**< ClassBody. */
    bool HasConstOrFrozenInit()
    {
        if (!hasConstOrFrozenInit.has_value()) {
            const auto& decls = body->decls;
            bool has = std::find_if(decls.cbegin(), decls.cend(), [](const OwnedPtr<Decl>& decl) {
                return decl->TestAttr(Attribute::CONSTRUCTOR) &&
                    (decl->IsConst() || decl->HasAnno(AnnotationKind::FROZEN));
            }) != decls.cend();
            hasConstOrFrozenInit = {has};
        }
        return *hasConstOrFrozenInit;
    }

    ClassDecl() : ClassLikeDecl(ASTKind::CLASS_DECL)
    {
    }

    Ptr<ClassDecl> GetSuperClassDecl() const
    {
        Ptr<ClassDecl> ret = nullptr;
        for (auto& it : inheritedTypes) {
            if (it->ty && it->ty->kind == TypeKind::TYPE_CLASS) {
                ret = static_cast<ClassTy*>(it->ty.get())->decl;
                break;
            }
        }
        return ret;
    }
    std::vector<OwnedPtr<Decl>>& GetMemberDecls() override
    {
        return body ? body->decls : Decl::GetMemberDecls();
    }

    bool IsOpen() const noexcept override
    {
        return TestAnyAttr(Attribute::OPEN, Attribute::ABSTRACT);
    }

private:
    std::optional<bool> hasConstOrFrozenInit{std::nullopt};
};

/**
 * An ExtendDecl node represents a extend declaration.
 */
struct ExtendDecl : InheritableDecl {
    OwnedPtr<Type> extendedType;         /**< The type being extended. */
    Position wherePos;                   /**< Position of 'where'. */
    OwnedPtr<DummyBody> bodyScope;       /**< split body scope for LSP. */
    Position leftCurlPos;                /**< The position of '{'. */
    std::vector<OwnedPtr<Decl>> members; /**< Declarations of the extend decl. */
    Position rightCurlPos;               /**< The position of '}'. */
    ExtendDecl() : InheritableDecl(ASTKind::EXTEND_DECL)
    {
    }
    std::vector<OwnedPtr<Decl>>& GetMemberDecls() override
    {
        return members;
    }
    bool IsExportedDecl() const override;
};

/**
 * Placeholder for invalid declaration.
 */
struct InvalidDecl : Decl {
    explicit InvalidDecl(const Position& pos) : Decl(ASTKind::INVALID_DECL)
    {
        EnableAttr(Attribute::IS_BROKEN);
        begin = pos;
        end = pos;
        doNotExport = true;
    }
};

/**
 * Base class of patterns.
 */
struct Pattern : Node {
    Ptr<Expr> ctxExpr{nullptr}; /**< Expr to match pattern. */

protected:
    Pattern(ASTKind kind) : Node(kind)
    {
    }
};

/**
 * An InvalidPattern node represents the invalid pattern.
 */
struct InvalidPattern : Pattern {
    InvalidPattern() : Pattern(ASTKind::INVALID_PATTERN)
    {
        EnableAttr(Attribute::IS_BROKEN);
    }

    explicit InvalidPattern(const Position& pos) : Pattern(ASTKind::INVALID_PATTERN)
    {
        EnableAttr(Attribute::IS_BROKEN);
        begin = pos;
        end = pos;
    }
};

/**
 * A ConstPattern node represents the constant pattern.
 */
struct ConstPattern : Pattern {
    OwnedPtr<Expr> literal;              /**< Literal constant. Generated by parser */
    OwnedPtr<CallExpr> operatorCallExpr; /**< resolved "==" overloaded function call */
    ConstPattern() : Pattern(ASTKind::CONST_PATTERN)
    {
    }
};

/**
 * A WildcardPattern node represents the wildcard pattern.
 */
struct WildcardPattern : Pattern {
    WildcardPattern() : Pattern(ASTKind::WILDCARD_PATTERN)
    {
    }

    explicit WildcardPattern(const Position& begin) : Pattern(ASTKind::WILDCARD_PATTERN)
    {
        this->begin = begin;
        this->end = begin + static_cast<size_t>(Len(TokenKind::WILDCARD));
    }
};

/**
 * A VarPattern node represents the variable pattern.
 */
struct VarPattern : Pattern {
    OwnedPtr<VarDecl> varDecl;  /**< Matched variable. Generated by parser */
    OwnedPtr<Expr> desugarExpr; /**< DesugarExpr for varDecl in TypePattern. */

    VarPattern() : Pattern(ASTKind::VAR_PATTERN)
    {
    }
    explicit VarPattern(SrcIdentifier ident, const Position& nodePos = {}) : Pattern(ASTKind::VAR_PATTERN)
    {
        varDecl = MakeOwned<VarDecl>();
        varDecl->begin = nodePos;
        varDecl->identifier = std::move(ident);
        varDecl->end = nodePos;
        varDecl->end = varDecl->identifier.End();
        varDecl->isVar = false;
        begin = nodePos;
        end = varDecl->end;
        varDecl->parentPattern = this;
    }
};

/**
 * A TuplePattern node represents the tuple pattern.
 */
struct TuplePattern : Pattern {
    Position leftBracePos;
    std::vector<OwnedPtr<Pattern>> patterns; /**< Each pattern in the tuple pattern. */
    std::vector<Position> commaPosVector;
    Position rightBracePos;
    TuplePattern() : Pattern(ASTKind::TUPLE_PATTERN)
    {
    }
};

/**
 * A TypePattern node represents the type pattern.
 */
struct TypePattern : Pattern {
    OwnedPtr<Pattern> pattern;              /**< WildPattern or VarPattern. Generated by Parser */
    Position colonPos;                      /**< Position of ':'. Generated by Parser */
    OwnedPtr<Type> type;                    /**< Type of the pattern. Generated by Parser */
    OwnedPtr<Expr> desugarExpr;             /**< Desugar of upcast type pattern. */
    OwnedPtr<VarPattern> desugarVarPattern; /**< Desugar of downcast type pattern. */
    bool needRuntimeTypeCheck{true};        /**< Flag that notice if should do runtime type check. */
    bool matchBeforeRuntime{true};          /**< Flag that notice if type pattern is matched on compile time. */
    TypePattern() : Pattern(ASTKind::TYPE_PATTERN)
    {
    }
};

/**
 * A EnumPattern node represents the enum pattern.
 */
struct EnumPattern : Pattern {
    OwnedPtr<Expr> constructor;              /**< Constructor of the enum. Generated by Parser*/
    std::vector<OwnedPtr<Pattern>> patterns; /**< Each pattern in the enum parameters. Generated by Parser*/
    Position leftParenPos;                   /**< Position of '('. Generated by Parser*/
    std::vector<Position> commaPosVector;
    Position rightParenPos;                  /**< Position of ')'. Generated by Parser*/
    EnumPattern() : Pattern(ASTKind::ENUM_PATTERN)
    {
    }
    std::string GetIdentifier() const;
};

/**
 * A VarOrEnumPattern node represents a VarPattern or an EnumPattern.
 */
struct VarOrEnumPattern : public Pattern {
    /**< Identifier of the variable or the enum constructor.
     * (When it's text is raw identifier, the raw mark "``" will be removed.
     * e.g., name of "`type_1`" is "type_1".) Generated by Parser. */
    SrcIdentifier identifier;
    OwnedPtr<Pattern> pattern; /**< VarPattern or EnumPattern. */
    VarOrEnumPattern(const SrcIdentifier& id) : Pattern(ASTKind::VAR_OR_ENUM_PATTERN), identifier{id}
    {
    }
};

/**
 * A ExceptTypePattern node represents the exception type pattern.
 */
struct ExceptTypePattern : Pattern {
    OwnedPtr<Pattern> pattern;            /**< VarPattern. Generated by Parser*/
    Position patternPos;                  /**< Position of VarPattern. Generated by Parser*/
    Position colonPos;                    /**< Position of ':'. Generated by Parser*/
    std::vector<OwnedPtr<Type>> types;    /**< Types of exceptions. Generated by Parser*/
    std::vector<Position> bitOrPosVector; /**< Positions of '|'. Generated by Parser*/
    ExceptTypePattern() : Pattern(ASTKind::EXCEPT_TYPE_PATTERN)
    {
    }
};

/**
 * A CommandTypePattern node represents the effect type pattern.
 */
struct CommandTypePattern : Pattern {
    OwnedPtr<Pattern> pattern;            /**< VarPattern. Generated by Parser*/
    Position patternPos;                  /**< Position of VarPattern. Generated by Parser*/
    Position colonPos;                    /**< Position of ':'. Generated by Parser*/
    std::vector<OwnedPtr<Type>> types;    /**< Types of Effects. Generated by Parser*/
    std::vector<Position> bitOrPosVector; /**< Positions of '|'. Generated by Parser*/
    CommandTypePattern() : Pattern(ASTKind::COMMAND_TYPE_PATTERN)
    {
    }
};

/**
 * Base expression node.
 */
struct Expr : Node {
    OwnedPtr<Expr> desugarExpr;
    Ptr<Expr> sourceExpr{nullptr}; /**< the source Expr if this node is a desugarExpr. */
    Ptr<Expr> mapExpr{nullptr};    /**< recorded mapped Expr if this node is a cloned expr with side effect. */
    Position semiPos;              /**< Position of ';'. Generated by parser, Optional */
    /**
     * Struct constNumValue store the primitive types for an 'expr', we will extend some primitive types
     * like int and float to bigint and bigfloat, so struct which is convenient to store a member with
     * a non-trivial default constructor is used instead of union
     */
    enum class FlowStatus { NORMAL, OVER, UNDER };
    struct {
        IntLiteral asInt;
        struct {
            long double value{0}; /**< Parsed from literal by `stold`, storaged with high-precision. */
            FlowStatus flowStatus{FlowStatus::NORMAL}; /**< Indicate the value flow status */
        } asFloat;                                     /**< The original high-precision float number. */
        bool asBoolean{true};
    } constNumValue;

    /** Used to mark sugar kind which is desugared before typecheck.
     * Also used to mark desugared call expr like `Token(xxx)`
    */
    enum class SugarKind {
        QUEST,
        IF_LET,    // if-let Expression
        WHILE_LET, // while-let Expression
        FOR_IN_EXPR, // for-in Expression
        IS, // is Expression
        AS, // as Expression
        TOKEN_CALL, // call expr like: Token(xxx)
        NO_SUGAR   // Not a sugar at all.
    };

    /**
     * Mark the current node for desugar, indicates that the node or subnode contains the quest suffix(?).
     */
    OverflowStrategy overflowStrategy{
        OverflowStrategy::NA}; /**< For overflow strategy. Generated by parser, Optional */
    bool isConst{false};
    bool isBaseFunc{false};
    bool isInFlowExpr{false};
    bool hasSemi{false}; /**< Mark the expr has ';'. Generated by parser, Optional*/
    bool hasQuestSuffix{false};

    Expr() : Node(ASTKind::EXPR)
    {
    }
    ~Expr() override = default;

    virtual std::vector<Ptr<Type>> GetTypeArgs() const
    {
        return {};
    }

    bool IsReferenceExpr() const noexcept
    {
        return astKind == ASTKind::REF_EXPR || astKind == ASTKind::MEMBER_ACCESS;
    }

protected:
    Expr(ASTKind kind) : Node(kind)
    {
    }
};

/**
 * Represent wildcard left value expr.
 * e.g. _ in `_ = 1`
 */
struct WildcardExpr : Expr {
    WildcardExpr() : Expr(ASTKind::WILDCARD_EXPR)
    {
    }
    explicit WildcardExpr(const Position& begin) : Expr(ASTKind::WILDCARD_EXPR)
    {
        this->begin = begin;
        this->end = begin + static_cast<size_t>(Len(TokenKind::WILDCARD));
    }
};

/**
 * A Block Node represents block.
 */
struct Block : Expr {
    Position leftCurlPos;             /**< Position of '{'. Generated by Parser */
    std::vector<OwnedPtr<Node>> body; /**< Block body. Generated by Parser */
    Position rightCurlPos;            /**< Position of '}'. Generated by Parser */
    Position unsafePos;               /**< Position of 'unsafe'. Generated by Parser, Optional */
    Block() : Expr(ASTKind::BLOCK)
    {
    }
    Ptr<Node> GetLastExprOrDecl() const;
};

/**
 * An IfExpr node represents an if expression or an if-let expression
 */
struct IfExpr : Expr {
    Position ifPos;           /**< Position of 'if'. */
    Position leftParenPos;    /**< Position of '('. */
    OwnedPtr<Expr> condExpr;  /**< Condition Expr. Generated by Parser*/
    Position rightParenPos;   /**< Position of ')'. */
    OwnedPtr<Block> thenBody; /**< Then body. Generated by Parser*/
    Position elsePos;         /**< Position of 'else'. */
    OwnedPtr<Expr> elseBody;  /**< Else body. Generated by Parser*/
    bool isElseIf{false};     /**< Whether has else if block. Generated by Parser*/
    bool hasElse{false};      /**< Whether has else block. Generated by Parser*/
    SugarKind sugarKind = SugarKind::NO_SUGAR;
    IfExpr() : Expr(ASTKind::IF_EXPR)
    {
    }
};

/**
 * A LetPatternDestructor only appears in if expr or while expr condition.
 * such as: if(let Some(v) <- x) {...}
 */
struct LetPatternDestructor : Expr {
    std::vector<OwnedPtr<Pattern>> patterns;  /**< Patterns to be destructed. Generated by Parser*/
    std::vector<Position> orPos; /**< '|' that separates the patterns.*/
    Position backarrowPos;       /**< Position of '<-'. */
    OwnedPtr<Expr> initializer;  /**< Initialize Expr. Generated by Parser*/
    LetPatternDestructor() : Expr{ASTKind::LET_PATTERN_DESTRUCTOR}
    {
    }
};

/**
 * A TokenPart node represents Consecutive tokens separated by interpolation in quote expression.
 */
struct TokenPart : Expr {
    std::vector<Token> tokens;
    TokenPart() : Expr(ASTKind::TOKEN_PART)
    {
    }
    TokenPart(std::vector<Token>& tokens) : Expr(ASTKind::TOKEN_PART), tokens(tokens)
    {
        if (!tokens.empty()) {
            begin = tokens[0].Begin();
            end = tokens.back().End();
        }
    }
};

/**
 * A QuoteExpr node represents quote expression.
 */
struct QuoteExpr : Expr {
    Position quotePos;      /**< Position of 'quote'. */
    Position leftParenPos;  /**< Position of '('. */
    Position rightParenPos; /**< Position of ')'. */
    /**
     * Arguments of the quote expression, include DollarExpr and TokenPart.
     */
    std::vector<OwnedPtr<Expr>> exprs;
    QuoteExpr() : Expr(ASTKind::QUOTE_EXPR)
    {
    }
};

/**
 * One match case.
 */
struct MatchCase : Node {
    std::vector<OwnedPtr<Pattern>> patterns; /**< A collection of patterns connected by `|`. */
    std::vector<Position> bitOrPosVector;
    OwnedPtr<Expr> patternGuard;             /**< Pattern match some condition. */
    Position wherePos;                       /**< Position of 'where', only matters when patternGuard is not null. */
    Position arrowPos;                       /**< Position of '=>'. */
    OwnedPtr<Block> exprOrDecls;             /**< Actions when matching. */
    MatchCase() : Node(ASTKind::MATCH_CASE)
    {
    }
    void SetCtxExprForPatterns(Ptr<Expr> ctxExpr)
    {
        for (auto& pattern : patterns) {
            if (pattern) {
                pattern->ctxExpr = ctxExpr;
            }
        }
    }
};

/**
 * Simple match case.
 */
struct MatchCaseOther : Node {
    OwnedPtr<Expr> matchExpr;    /**< Simple match expr. Generated by Parser. */
    Position arrowPos;           /**< Position of '=>'. */
    OwnedPtr<Block> exprOrDecls; /**< Actions when matching. Generated by Parser.*/
    MatchCaseOther() : Node(ASTKind::MATCH_CASE_OTHER)
    {
    }
};

/**
 * A MatchExpr node represents match-case expression.
 */
struct MatchExpr : Expr {
    SugarKind sugarKind = SugarKind::NO_SUGAR;
    bool matchMode{false};   /**< Normal pattern match:true, Implement if-else if: false. Generated by Parser.*/
    Position leftParenPos;   /**< Position of '('. */
    OwnedPtr<Expr> selector; /**< The Expr to be match. */
    Position rightParenPos;  /**< Position of ')'. */
    Position leftCurlPos;    /**< Position of '{'. */
    std::vector<OwnedPtr<MatchCase>> matchCases;           /**< Match cases. */
    std::vector<OwnedPtr<MatchCaseOther>> matchCaseOthers; /**< No selector mode. */
    Position rightCurlPos;                                 /**< Position of '}'. */
    MatchExpr() : Expr(ASTKind::MATCH_EXPR)
    {
    }
};

struct Handler {
    Position pos;
    OwnedPtr<Pattern> commandPattern;
    OwnedPtr<Block> block;
    OwnedPtr<LambdaExpr> desugaredLambda;
    Ty* commandResultTy;
};

/**
 * A TryExpr node represents Try expression.
 */
struct TryExpr : Expr {
    Position tryPos;                              /**< Position of 'try'. */
    Position lParen;                              /**< Resource left paren position. */
    std::vector<OwnedPtr<VarDecl>> resourceSpec;  /**< Init several resources. */
    std::vector<Position> resourceSpecCommaPos;   /**< Resource comma positions. */
    Position rParen;                              /**< Resource right paren position. */
    OwnedPtr<Block> tryBlock;                     /**< Try block. */
    std::vector<Position> catchPosVector;         /**< Positions of 'catch'. */
    std::vector<Position> catchLParenPosVector;   /**< Positions of '(' in catch blocks. */
    std::vector<Position> catchRParenPosVector;   /**< Positions of ')' in catch blocks. */
    std::vector<OwnedPtr<Block>> catchBlocks;     /**< Several catch blocks. */
    std::vector<OwnedPtr<Pattern>> catchPatterns; /**< '_' or ExceptTypePattern. */
    Position finallyPos;                          /**< Position of 'finally'. */
    OwnedPtr<Block> finallyBlock;                 /**< Finally block. */
    std::vector<Handler> handlers;                /**< Handler cases in try/handle */
    bool isIllegalResourceSpec{false}; /**< Nested try expressions inside resource specifications are not allowed. */
    bool isDesugaredFromTryWithResources{
        false};                           /**< Desugared from try-with-resources expressions. Generated by Parser.*/
    bool isDesugaredFromSyncBlock{false}; /**< Desugared from synchronized expressions. For better error reporting. */
    OwnedPtr<LambdaExpr> tryLambda;     /**< Try block as a lambda. Used for desugaring try/handle */
    OwnedPtr<LambdaExpr> finallyLambda; /**< Finally block as a lambda. Used for desugaring try/handle */

    TryExpr() : Expr(ASTKind::TRY_EXPR)
    {
    }
};

/**
 * A ThrowExpr node represents throw expression.
 */
struct ThrowExpr : Expr {
    Position throwPos;   /**< Position of 'throw'. */
    OwnedPtr<Expr> expr; /**< Throw expr. */
    ThrowExpr() : Expr(ASTKind::THROW_EXPR)
    {
    }
};

/**
 * A PerformExpr node represents perform expression.
 */
struct PerformExpr : Expr {
    Position performPos; /**< Position of 'perform'. */
    OwnedPtr<Expr> expr; /**< Perform expr. */
    PerformExpr() : Expr(ASTKind::PERFORM_EXPR)
    {
    }
};

/**
 * A ResumeExpr node represents resume expression.
 */
struct ResumeExpr : Expr {
    Position resumePos;                    /**< Position of 'resume'. */
    Position withPos;                      /**< Position of 'with' (optional). */
    OwnedPtr<Expr> withExpr;               /**< With expr (optional). */
    Position throwingPos;                  /**< Position of 'throwing' (optional). */
    OwnedPtr<Expr> throwingExpr;           /**< Throwing expr (optional). */
    std::optional<Ptr<Handler>> enclosing; /**< Pointer to the (immediate) enclosing handler, if any. */
    ResumeExpr() : Expr(ASTKind::RESUME_EXPR)
    {
    }
};
/**
 * A ReturnExpr node represents return expression.
 */
struct ReturnExpr : Expr {
    Position returnPos;                 /**< Position of 'return'. */
    OwnedPtr<Expr> expr;                /**< Return expr. Generated by Parser.*/
    Ptr<FuncBody> refFuncBody{nullptr}; /**< In which function body. */
    ReturnExpr() : Expr(ASTKind::RETURN_EXPR)
    {
    }
};

/**
 * A JumpExpr node represents continue or break expression.
 */
struct JumpExpr : Expr {
    Ptr<Expr> refLoop{nullptr}; /**< In which loop expr. */
    bool isBreak{false};        /**< Break: true, Continue: false. Generated by Parser.*/
    JumpExpr() : Expr(ASTKind::JUMP_EXPR)
    {
    }
};

/**
 * A ForInExpr node represents for-in expression.
 */
struct ForInExpr : Expr {
    Position leftParenPos;     /**< Position of '('. */
    OwnedPtr<Pattern> pattern; /**< Same Pattern in the pattern match. */
    Ptr<Pattern> patternInDesugarExpr{nullptr};
    Position inPos;              /**< Position of 'in'. */
    OwnedPtr<Expr> inExpression; /**< In some expr. Generated by Parser.*/
    Position rightParenPos;      /**< Position of ')'. */
    Position wherePos;           /**< Position of 'if'. */
    OwnedPtr<Expr> patternGuard; /**< Same PatternGuard in the pattern match. Generated by Parser.*/
    OwnedPtr<Block> body;        /**< Body of the ForInExpr. Generated by Parser.*/
    ForInKind forInKind;
    ForInExpr() : Expr(ASTKind::FOR_IN_EXPR), forInKind(ForInKind::FORIN_INVALID)
    {
    }

    /// Test whether the range expression of this forin is closed range, and the step is either missing, or literal one.
    /// Some CHIR optimization depends on this.
#ifdef CANGJIE_CODEGEN_CJNATIVE_BACKEND
    bool IsClosedRangeOne() const;
#endif
};

/**
 * A WhileExpr node represents while expression.
 */
struct WhileExpr : Expr {
    Position whilePos;       /**< Position of 'while'. */
    Position leftParenPos;   /**< Positin of '('. */
    OwnedPtr<Expr> condExpr; /**< While condition. */
    Position rightParenPos;  /**< Position of ')'. */
    OwnedPtr<Block> body;    /**< Body of the WhileExpr. */
    SugarKind sugarKind = SugarKind::NO_SUGAR;
    WhileExpr() : Expr(ASTKind::WHILE_EXPR)
    {
    }
};

/**
 * A DoWhileExpr node represents do-while expression.
 */
struct DoWhileExpr : Expr {
    Position doPos;          /**< Position of 'do'. */
    OwnedPtr<Block> body;    /**< Body of the DoWhileExpr. */
    Position whilePos;       /**< Position of 'while'. */
    Position leftParenPos;   /**< Position of '('. */
    OwnedPtr<Expr> condExpr; /**< Do while condition. */
    Position rightParenPos;  /**< Position of ')'. */
    DoWhileExpr() : Expr(ASTKind::DO_WHILE_EXPR)
    {
    }
};

/**
 * An OverloadableExpr represents an expr whose operator can be overloaded.
 * OverloadableExpr: AssignExpr, UnaryExpr, BinaryExpr, ArrayAccess.
 */
struct OverloadableExpr : Expr {
    TokenKind op{TokenKind::ILLEGAL}; /**< Operator kind. */
protected:
    OverloadableExpr(ASTKind kind) : Expr(kind)
    {
    }
};

/**
 * An AssignExpr Node represents assignment expression.
 * example:
 *          a = b
 *          ^^^^^
 */
struct AssignExpr : OverloadableExpr {
    OwnedPtr<Expr> leftValue; /**< Left hand side expr. */
    Position assignPos{};     /**< Position of the assign operator. */
    OwnedPtr<Expr> rightExpr; /**< Right hand side expr. */
    bool isCompound = false;
    AssignExpr() : OverloadableExpr(ASTKind::ASSIGN_EXPR)
    {
    }
    void Clear() noexcept override;
};

/**
 * An IncOrDecExpr node represents inc or dec expression.
 * e.g.
 *          a++  or  a--
 *          ^^^      ^^^
 */
struct IncOrDecExpr : OverloadableExpr {
    Position operatorPos; /**< Position of '++' or '--'. */
    OwnedPtr<Expr> expr;
    IncOrDecExpr() : OverloadableExpr(ASTKind::INC_OR_DEC_EXPR)
    {
    }
};

/**
 * UnaryExpr node represents unary operation expression.
 * e.g.
 *          !a  or  -a
 *          ^^      ^^
 */
struct UnaryExpr : OverloadableExpr {
    OwnedPtr<Expr> expr;  /**< The unary expr. */
    Position operatorPos; /**< Position of '- !'. */
    UnaryExpr() : OverloadableExpr(ASTKind::UNARY_EXPR)
    {
    }
    void Clear() noexcept override;
};

/**
 * BinaryExpr node represents binary operation expression.
 * e.g.
 *          a + b  or  a % b
 *          ^^^^^      ^^^^^
 */
struct BinaryExpr : OverloadableExpr {
    OwnedPtr<Expr> leftExpr;  /**< Left expr. */
    OwnedPtr<Expr> rightExpr; /**< Right expr. */
    Position operatorPos;     /**< Position of '&&', '||', etc. */
    BinaryExpr() : OverloadableExpr(ASTKind::BINARY_EXPR)
    {
    }
    void Clear() noexcept override;
};

/**
 * IsExpr node represents `is` operation expression.
 */
struct IsExpr : Expr {
    OwnedPtr<Expr> leftExpr; /**< Left expr. Generated by Parser.*/
    OwnedPtr<Type> isType;   /**< Right type. Generated by Parser.*/
    Position isPos;          /**< Position of 'is'. */
    IsExpr() : Expr(ASTKind::IS_EXPR)
    {
    }
};

/**
 * AsExpr node represents `as` operation expression.
 */
struct AsExpr : Expr {
    OwnedPtr<Expr> leftExpr; /**< Left expr. */
    OwnedPtr<Type> asType;   /**< Right type. */
    Position asPos;          /**< Position of 'as'. */
    AsExpr() : Expr(ASTKind::AS_EXPR)
    {
    }
};

/**
 * RangeExpr node represents range expression like 'a...b:c'.
 */
struct RangeExpr : Expr {
    OwnedPtr<Expr> startExpr;       /**< No start will be @c nullptr. Generated by parser */
    Position rangePos;              /**< Position of '...'.Generated by parser */
    OwnedPtr<Expr> stopExpr;        /**< No stop will be @c nullptr. Generated by parser */
    Position colonPos;              /**< Position of ':'. Generated by parser */
    OwnedPtr<Expr> stepExpr;        /**< No step will be @c nullptr. Generated by parser */
    Ptr<StructDecl> decl = nullptr; /**< StructDecl for Range literals. */
    bool isClosed{true};            /**< A flag to mark this is closed range or a half-open range. */
    RangeExpr() : Expr(ASTKind::RANGE_EXPR)
    {
    }
};

/**
 * SubscriptExpr node represents an index access expression.
 * e.g.
 *          a[x]  or  b[1][2]
 *          ^^^^      ^^^^^^^
 */
struct SubscriptExpr : OverloadableExpr {
    OwnedPtr<Expr> baseExpr;                /**< Left parts split by last '['. Generated by Parser.*/
    Position leftParenPos;                  /**< Position of '['. */
    std::vector<OwnedPtr<Expr>> indexExprs; /**< Exprs between '[' and ']'. Generated by Parser.*/
    std::vector<Position> commaPos;
    Position rightParenPos;                 /**< Position of ']'. */
    /**
     * Whether the baseExpr is of type tuple.
     * Currently, after desugaring, a SubscriptExpr can only be an access to a tuple or a varray.
     */
    bool isTupleAccess{false};
    bool IsVArrayAccess() const
    {
        return baseExpr && baseExpr->ty->kind == TypeKind::TYPE_VARRAY;
    }
    SubscriptExpr() : OverloadableExpr(ASTKind::SUBSCRIPT_EXPR)
    {
    }
    void Clear() noexcept override;
};

/**
 * InterpolationExpr node represents Interpolation expression in String like "${b}".
 */
struct InterpolationExpr : Expr {
    std::string rawString; /**< The Interpolation string "${a}". Generated by Parser.*/
    Position dollarPos;    /**< Position of '$'. */
    OwnedPtr<Block> block; /**< { a + b }, Generated by Parser.*/
    InterpolationExpr() : Expr(ASTKind::INTERPOLATION_EXPR)
    {
    }
};

/**
 * StrInterpolationExpr node represents String Interpolation expression like "a ${b} c".
 */
struct StrInterpolationExpr : Expr {
    std::string rawString;            /**< The value of string Interpolation "a ${b} c". Generated by Parser.*/
    std::vector<StringPart> strParts; /**< StringPart in string Interpolation. Generated by Parser.*/
    /**
     * strPartExprs separated by interpolation, include string LitConstExpr and InterpolationExpr. Generated by Parser.
     */
    std::vector<OwnedPtr<Expr>> strPartExprs;
    StrInterpolationExpr() : Expr(ASTKind::STR_INTERPOLATION_EXPR)
    {
    }
};

/**
 * LitConstKind contains all literal kind.
 * This enum has a correspondence with class TokenKindHelper in std.ast/TokenKind.cj
 * They need to be changed respectively at the same time.
 */
enum class LitConstKind : uint8_t {
    INTEGER,           /**< Int8, Int16, Int32, Int64, UInt8, etc. */
    RUNE_BYTE,         /**< UInt8 type such as b'a', b'\n' literals */
    FLOAT,             /**< float16, float32, float64. */
    RUNE,              /**< Rune. */
    STRING,            /**< String. */
    JSTRING,           /**< JString. */
    BOOL,              /**< bool. */
    UNIT,              /**< Unit. */
    NONE               /**< None literal const. */
};

/**
 * There should not be a need to treat literals of different primitives types as different C++ classes instead, just
 * fill the type in Expr during parsing, which is the only field that needs any testing
 */
struct LitConstExpr : Expr {
    OwnedPtr<RefType> ref;                     /**< RefType for String literals. */
    std::string rawString;                     /**< The literal raw string for fmt. Generated by Parser.*/
    OwnedPtr<StrInterpolationExpr> siExpr;     /**< string interpolation expression. Generated by Parser.*/
    std::string stringValue;                   /**< The literal string representation. Generated by Parser.*/
    std::vector<uint32_t> codepoint;           /**< Code point of the character in the string. Generated by Parser.*/
    LitConstKind kind{LitConstKind::NONE};     /**< Literal const kind. Generated by Parser.*/
    StringKind stringKind{StringKind::NORMAL}; /**< Kind of String. Generated by Parser.*/
    bool isSingleQuote{false};                 // Quotations of string-related literals can be single or double.
    unsigned int delimiterNum{1};              /**< Delimiter '#' number for raw string. Generated by Parser.*/
    LitConstExpr() : Expr(ASTKind::LIT_CONST_EXPR)
    {
    }
    LitConstExpr(LitConstKind kind, std::string str)
        : Expr(ASTKind::LIT_CONST_EXPR), stringValue(std::move(str)), kind(kind)
    {
    }

    std::string LitKindToString() const
    {
        switch (kind) {
            case LitConstKind::INTEGER:
                return "Integer";
            case LitConstKind::RUNE_BYTE:
                return "RuneByte";
            case LitConstKind::FLOAT:
                return "Float";
            case LitConstKind::RUNE:
                return "Rune";
            case LitConstKind::STRING:
                return "String";
            case LitConstKind::JSTRING:
                return "JString";
            case LitConstKind::BOOL:
                return "Bool";
            case LitConstKind::UNIT:
                return "Unit";
            case LitConstKind::NONE:
                return "None";
        }
    }
    std::string ToString() const override;
    // Get number literal type kind from suffix, if no suffix TYPE_IDEAL will be returned
    TypeKind GetNumLitTypeKind();
};

/**
 * A MacroInvocation represents Macro Invocation Information.
 */
struct MacroInvocation {
    // Read only. Determined in Parsing.
    std::string fullName;                 /**< Full name of the Macro Call: p1.Moo. Generated by parser */
    std::vector<Position> fullNameDotPos; /**< Dot positions in full name. Generated by parser */
    std::string identifier;               /**< Macro name: Moo. Generated by parser */
    Position identifierPos;               /**< Position of the MacroCall's identifier. Generated by parser */
    Position leftSquarePos;               /**< Position of '['. Generated by parser, Optional */
    Position rightSquarePos;              /**< Position of ']'. Generated by parser, Optional */
    Position leftParenPos;                /**< Position of '('. Generated by parser, Optional */
    Position rightParenPos;               /**< Position of ')'. Generated by parser, Optional */
    Position atPos;                       /**< The position of '@'. Generated by parser. */
    Position macroNamePos;                /**< The real position of Macro name: Moo. Generated by parser. */
    std::vector<Token> attrs;             /**< Attributes to Macro. */
    bool HasAttr()
    {
        return hasAttr;
    }
    std::vector<Token> args;   /**< Arguments to the Macro. */
    OwnedPtr<Decl> decl;       /**< ASTKind of the Decl as Macro's args. */
    Ptr<Node> parent{nullptr}; /**< Parent node. */
    Ptr<Decl> target{nullptr}; /**< Target node. */
    // For primary ctor decl. Need to reconsider this.
    std::string outerDeclIdent; /**< MacroExpandDecl's parent decl identifier. */
    // Arguments include macroExpression and TokenPart.
    std::vector<OwnedPtr<Node>> nodes;
    std::vector<Position> macroAtPosition; /**< all macros' begin position. */

    std::vector<Token> newTokens; /**< Tokens after macro evaluation. */
    std::string newTokensStr;     /**< Tokens str after macro evaluation. */
    std::variant<ScopeKind, ExprKind> scope;

    bool hasParenthesis{false};
    bool hasAttr{false};
    bool isFuncParam{false};
    bool isCustom{false}; /**< Indicates Custom Annotation. */
    bool isCompileTimeVisible{}; /**< True when @! Annotation. */
    // Mapping between new position column and origin source position in macrocall for debug.
    std::map<unsigned int, Position, std::greater<unsigned int>> macroDebugMap;
    // Mapping between new position column and origin source position before macro expansion.
    std::map<unsigned int, Position, std::greater<unsigned int>> new2originPosMap;
    // Mapping between new position column and new source position after macro expansion.
    std::map<unsigned int, Position, std::greater<unsigned int>> new2macroCallPosMap;
    // Mapping between hash of origin position and new position after macro expansion.
    std::map<uint64_t, Position, std::greater<uint64_t>> origin2newPosMap;
    // Mapping between hash of origin position and begin position of origin token before macro expansion.
    std::map<unsigned int, Position, std::greater<unsigned int>> originPosMap;
    bool isCurFile{false};
    bool isForLSP{false};
    bool hasShownCode{false}; /**< Has shown the code that generated by macro once in diagnostics. */
    Position mcBegin;         /**< Begin position of new source after macro expansion. */
    Position mcEnd;           /**< End position of new source after macro expansion. */
    /// True if this is an @IfAvailable node. For compatibility, @IfAvailable node is tucked into a MacroExpandExpr
    /// and translated to IfExpr later.
    bool IsIfAvailable() const;
};

/**
 * A MacroExpandExpr node represents where Macro need to be expanded.
 * When and only when representing a @IfAvailable(namedParam: arg, lambda1, lambda2), methods GetNamedArg and GetLambda
 * are available to get the sub-exprs. They are put into invocation.nodes just for backward compatibility of ast nodes.
 */
struct MacroExpandExpr : Expr {
    MacroInvocation invocation;                    /**< MacroExpand Invoking Information. */
    Identifier identifier;                         /**< Macro name: Moo */
    std::vector<OwnedPtr<Annotation>> annotations; /**< Annotation set of the Decl. */
    std::set<Modifier> modifiers;                  /**< Modifier set of the Decl. */
    MacroExpandExpr() : Expr(ASTKind::MACRO_EXPAND_EXPR)
    {
    }

    Ptr<FuncArg> GetNamedArg() const;
    Ptr<struct LambdaExpr> GetLambda(size_t i) const;
    /// Get the inner exprs. Used in desugar.
    std::tuple<OwnedPtr<FuncArg>, OwnedPtr<struct LambdaExpr>, OwnedPtr<struct LambdaExpr>> Decompose();
};

/**
 * A MacroExpandDecl node represents where Macro need to be expanded.
 */
struct MacroExpandDecl : Decl {
    MacroInvocation invocation; /**< MacroExpandDecl Invoking Information. */
    MacroExpandDecl() : Decl(ASTKind::MACRO_EXPAND_DECL)
    {
    }
};

/**
 * A MacroExpandParam node represents where Macro need to be expanded in the params list.
 */
struct MacroExpandParam : FuncParam {
    MacroInvocation invocation;
    MacroExpandParam() : FuncParam(ASTKind::MACRO_EXPAND_PARAM)
    {
        invocation.isFuncParam = true;
    }
};
/**
 * Function arguments in CallExpr.
 */
struct FuncArg : Node {
    SrcIdentifier name;              /**< Argument name. Generated by parser, Optional */
    Position colonPos;               /**< Position of ':'. Generated by parser, Optional */
    OwnedPtr<Expr> expr;             /**< The expr of the argument.  Generated by parser */
    Position commaPos;               /**< Position of ','.  Generated by parser, Optional */
    bool withInout{false};           /**< Indicate if modified with 'inout'. Generated by parser, Optional */
    Position inoutPos;               /**< Position of 'inout'. Generated by parser, Optional */
    FuncArg() : Node(ASTKind::FUNC_ARG)
    {
    }
    void Clear() noexcept override
    {
        Node::Clear();
        if (expr != nullptr) {
            expr->Clear();
        }
        DisableAttr(Attribute::HAS_INITIAL);
    }
    std::string ToString() const override;
};

/**
 * Which function call.
 */
enum class CallKind {
    CALL_INVALID = 0,       /**< Invalid call. */
    CALL_DECLARED_FUNCTION, /**< Normal function call. */
    CALL_OBJECT_CREATION,   /**< Create an object. */
    CALL_FUNCTION_PTR,      /**< Function point invoke. */
    CALL_STRUCT_CREATION,   /**< Create a struct. */
    CALL_SUPER_FUNCTION,    /**< Is super() function call. */
    CALL_VARIADIC_FUNCTION, /**< Variadic function call. */
    CALL_ANNOTATION,        /**< Custom annotation call. */
    // Todo: remove
    CALL_BUILTIN_FUNCTION,  /**< Is buildin api call. */
    CALL_INTRINSIC_FUNCTION /**< Is intrinsic function call. */
};

/**
 * CallExpr node represents function-call expression.
 */
struct CallExpr : Expr {
    OwnedPtr<Expr> baseFunc;                   /**< The expr, may be RefExpr or MemberAccess. Generated by Parser. */
    Position leftParenPos;                     /**< Position of '('. */
    std::vector<OwnedPtr<FuncArg>> args;       /**< Arguments to the function. */
    Position rightParenPos;                    /**< Position of ')'. */
    Ptr<FuncDecl> resolvedFunction{nullptr};   /**< Resolved called function. */
    CallKind callKind{CallKind::CALL_INVALID}; /**< Kind of the call. */
    std::optional<std::vector<Ptr<FuncArg>>>
        desugarArgs; /**< It points to args and defaultArgs, which are used to do the real parameter sorting. When
                        it is none, the callExpr does not go into args reordering. */
    std::vector<OwnedPtr<FuncArg>> defaultArgs; /**< The defaultArgs used to store supplements for default args*/

    bool needCheckToTokens{
        false}; /**< A flag to mark whether the call is needed to check implementing interface ToTokens . */
    SugarKind sugarKind = SugarKind::NO_SUGAR;

    CallExpr() : Expr(ASTKind::CALL_EXPR)
    {
    }
    void Clear() noexcept override;

    std::string ToString() const override;
};

/**
 * NameReferenceExpr is used as an attribute holder abstraction for RefExpr and MemberAccess.
 */
struct NameReferenceExpr : Expr {
    Position leftAnglePos;                     /**< The position of left angle bracket '<'. */
    std::vector<OwnedPtr<Type>> typeArguments; /**< Instantiation type. */
    Position rightAnglePos;                    /**< The position of right angle bracket '>'. */
    /** The type arguments type if call generic function without explicit type arguments. */
    std::vector<Ptr<Ty>> instTys;
    /** The func call or pattern whose baseFunc is this ref */
    Ptr<Node> callOrPattern{nullptr};
    Ptr<Ty> matchedParentTy{nullptr}; /**< The determined parent ty of current reference's context structure type. */
    /** For LSP. Point to typeAliasDecl if the current reference is aliased name. Can be ignored in clone. */
    Ptr<TypeAliasDecl> aliasTarget{nullptr};
    bool isAlone{true}; /**< Whether the current expr is separately written. Generated by Parser. */
    /** Whether the type arguments are added by compiler, instead of from src code.
     *  Only happens if this reference points to a type alias. */
    bool compilerAddedTyArgs{false};

    std::vector<Ptr<Type>> GetTypeArgs() const override
    {
        return ConverVector(typeArguments);
    }

    size_t OuterArgSize() const;

protected:
    NameReferenceExpr(ASTKind astKind) : Expr(astKind)
    {
    }
    NameReferenceExpr(const NameReferenceExpr&) = delete;
    NameReferenceExpr& operator=(const NameReferenceExpr&) = delete;
};

/**
 * MemberAccess node represents object member access expression like obj.a.b.
 */
struct MemberAccess : NameReferenceExpr {
    OwnedPtr<Expr> baseExpr; /**< Left parts split by last '.'. */
    Position dotPos;         /**< Position of the right most '.'. */
    /**< Right parts split by last '.'. (When it's text is raw identifier, the raw mark "``" will be removed.
     * e.g., name of "`type_1`" is "type_1".) */
    SrcIdentifier field;
    std::vector<Ptr<FuncDecl>> targets; /**< If the accessed symbol is a function name, this field stores overloaded
                                       function definitions. */
    Ptr<Decl> target{nullptr}; /**< If the accessed symbol is not a function name, this field stores the target. */
    std::unordered_map<Ptr<Decl>, std::unordered_set<Ptr<Ty>>>
        foundUpperBoundMap;      /**< The targets in all upperBounds. */
    bool isExposedAccess{false}; /**< Whether the current expr is exposed to upper bound. */
    bool isPattern{false};       /**< Whether the current expr is inside a pattern. Generated by Parser.*/
    MemberAccess() : NameReferenceExpr(ASTKind::MEMBER_ACCESS)
    {
    }
    void Clear() noexcept override
    {
        Expr::Clear();
        baseExpr->Clear();
        foundUpperBoundMap.clear();
        target = nullptr;
        targets.clear();
        instTys.clear();
        isExposedAccess = false;
        matchedParentTy = nullptr;
        desugarExpr = OwnedPtr<Expr>();
    }

    std::string ToString() const override;
    /**
     * Get the field Position of the MemberAccess.
     * @return field Position in macrocall file if the MemberAccess is expanded from macrocall,
     *  field position in curfile otherwise.
     */
    Position GetFieldPos() const;
};

/**
 * A ParenExpr node represents a parenthesized expression which the expression between "(" and ")".
 * ```
 * a = (1+2)*3;
 * ```
 */
struct ParenExpr : Expr {
    Position leftParenPos;  /**< Position of '('. */
    OwnedPtr<Expr> expr;    /**< Expr between '(' and ')'. */
    Position rightParenPos; /**< Position of ')'. */
    ParenExpr() : Expr(ASTKind::PAREN_EXPR)
    {
    }
    void Clear() noexcept override;
};

/**
 * A lambdaExpr node represents a lambda expression with '=>'.
 */
struct LambdaExpr : Expr {
    LambdaExpr() : Expr(ASTKind::LAMBDA_EXPR)
    {
    }
    OwnedPtr<FuncBody> funcBody; /**< Funcbody of lambda. */
    std::string mangledName; /**< The name after mangling. */
    explicit LambdaExpr(OwnedPtr<FuncBody> body) : Expr(ASTKind::LAMBDA_EXPR), funcBody(std::move(body))
    {
    }
};

struct TrailingClosureExpr : Expr {
    Position leftLambda;         /**< Left Position of Lambda. */
    OwnedPtr<Expr> expr;         /**< refExpr or callExpr. */
    OwnedPtr<LambdaExpr> lambda; /**< tail closure package. */
    Position rightLambda;        /**< Right Position of Lambda. */
    TrailingClosureExpr() : Expr(ASTKind::TRAIL_CLOSURE_EXPR)
    {
    }
};

struct OptionalExpr : Expr {
    OwnedPtr<Expr> baseExpr;
    Position questPos; /**< The position of '?'. */
    explicit OptionalExpr() : Expr(ASTKind::OPTIONAL_EXPR)
    {
    }
};

struct OptionalChainExpr : Expr {
    OwnedPtr<Expr> expr;
    explicit OptionalChainExpr() : Expr(ASTKind::OPTIONAL_CHAIN_EXPR)
    {
    }
};

/**
 * An ArrayLit node represents a List literal with expressions between comma.
 * ```
 * [1, 2, 3, 4, 5]
 * ```
 */
struct ArrayLit : Expr {
    Position leftSquarePos;               /**< Position of '['. */
    std::vector<OwnedPtr<Expr>> children; /**< Children in the list. */
    std::vector<Position> commaPosVector; /**< Positions of commas. */
    Position rightSquarePos;              /**< Position of ']'. */
    Ptr<FuncDecl> initFunc{nullptr};
    ArrayLit() : Expr(ASTKind::ARRAY_LIT)
    {
    }
    std::string ToString() const override;
};

/**
 * An ArrayExpr node represents a 'RawArray' or a 'VArray' constructing expressions.
 * For RawArray it can be:
 * ```
 * RawArray<Int32>()
 * RawArray<Int32>(n, 9)
 * RawArray<Int32>(5, (i) => {i * 2})
 * RawArray<Int32>(Collection/List)
 * ```
 * For VArray it can be:
 * ```
 * VArray<Int32, $3>(repeat: 1)
 * VArray<Int64, $3>({i => i})
 * ```
 */
struct ArrayExpr : public Expr {
    OwnedPtr<Type> type;                  /**< Array type. Generated by Sema */
    Position leftParenPos;                /**< Position of '('. */
    std::vector<OwnedPtr<FuncArg>> args;  /**< Generated by Sema */
    std::vector<Position> commaPosVector; /**< Generated by Sema */
    Position rightParenPos;               /**< Position of ')'. Generated by Sema */
    Ptr<FuncDecl> initFunc{nullptr};
    bool isValueArray{false}; /* Is a VArray expr or not. */
    ArrayExpr() : Expr(ASTKind::ARRAY_EXPR)
    {
    }
    std::string ToString() const override;
};

/**
 * Represents an Pointer Constructor.
 * Currently, only two kinds: init()，init(origin: CPointer<U>).
 */
struct PointerExpr : Expr {
    OwnedPtr<Type> type;   /**< Pointer type. */
    OwnedPtr<FuncArg> arg; /**< Arguments to the constructor, one or none. */
    PointerExpr() : Expr(ASTKind::POINTER_EXPR)
    {
    }
    std::string ToString() const override;
};

/**
 * A TupleLit node represents a tuple literal with expressions between comma.
 * ```
 * (1, 2, 3, 4)
 * ```
 */
struct TupleLit : Expr {
    Position leftParenPos;                /**< Position of '('. */
    std::vector<OwnedPtr<Expr>> children; /**< Children of tuple. */
    std::vector<Position> commaPosVector; /**< Positions of commas. */
    Position rightParenPos;               /**< Position of ')'. */
    TupleLit() : Expr(ASTKind::TUPLE_LIT)
    {
    }
};

/**
 * A TypeConvExpr node represents numeric type convert expression.
 */
struct TypeConvExpr : Expr {
    OwnedPtr<Type> type;    /**< Must be numeric or function type. */
    Position leftParenPos;  /**< Position of '('. */
    OwnedPtr<Expr> expr;    /**< The expr to be convert. */
    Position rightParenPos; /**< Position of ')'. */
    TypeConvExpr() : Expr(ASTKind::TYPE_CONV_EXPR)
    {
    }
};

/**
 * RefExpr represents an expression of reference.
 */
struct RefExpr : NameReferenceExpr {
    Reference ref; /**< Reference of the expr. */
    bool isThis{false};
    bool isSuper{false};
    bool isQuoteDollar{false};
    RefExpr() : NameReferenceExpr(ASTKind::REF_EXPR)
    {
    }
    void Clear() noexcept override
    {
        Expr::Clear();
        ref.target = nullptr;
        ref.targets.clear();
        instTys.clear();
        matchedParentTy = nullptr;
    }

    std::string ToString() const override;
    /**
     * Get the identifier Position of the RefExpr.
     * @return identifier Position in macrocall file if the RefExpr is expanded from macrocall,
     *  identifier position in curfile otherwise.
     */
    Position GetIdentifierPos() const;
};

/**
 * A PrimitiveTypeExpr is a placeholder Expr for primitive type static function call.
 * e.g. Int64.foo() is a MemberAccess, whose baseExpr is a PrimitiveTypeExpr, where its TypeKind =
 * TypeKind::TYPE_INT64.
 */
struct PrimitiveTypeExpr : Expr {
    TypeKind typeKind;
    explicit PrimitiveTypeExpr(TypeKind typeKind) : Expr(ASTKind::PRIMITIVE_TYPE_EXPR), typeKind(typeKind)
    {
    }
};

/**
 * Placeholder for invalid expression.
 */
struct InvalidExpr : Expr {
    std::string value;
    InvalidExpr() : Expr(ASTKind::INVALID_EXPR)
    {
        EnableAttr(Attribute::IS_BROKEN);
    }
    explicit InvalidExpr(const Position& pos) : Expr(ASTKind::INVALID_EXPR)
    {
        EnableAttr(Attribute::IS_BROKEN);
        begin = pos;
        end = pos;
    }
};

 /**
 * FeatureId
 *      : Identifier (DOT Identifier)*
 *      ;
 */
struct FeatureId : Node {
    std::vector<Identifier> identifiers;    /**< identifiers with positions */
    std::vector<Position> dotPoses;         /**< position of dots */
    FeatureId() : Node(ASTKind::FEATURE_ID)
    {
    }
    std::string ToString() const override;
};

/**
 * A FeaturesDirective represents a feature set in file header.
 * featuresDirective
 *      : FEATURES NL* FeatureId
 *      (COMMA NL* FeatureId)*
 *      end+;
 */
struct FeaturesDirective : Node {
    std::vector<FeatureId> content;      /**< content of featuresDirective*/
    std::vector<Position> commaPoses;    /**< comma poses */
    FeaturesDirective() : Node(ASTKind::FEATURES_DIRECTIVE)
    {
    }
};

enum class ImportKind {
    IMPORT_SINGLE,
    IMPORT_ALIAS,
    IMPORT_ALL,
    IMPORT_MULTI,
};

/**
 * single import: a.b.c or a::b.c
 * multi import: a.b.{c, d} or a::b.{c, d} or a::{c, d}
 * alias import: a.b as ab or a::b as orgaB
 * import all: a.b.* or a::b.*. a::* is invalid.
 */
struct ImportContent : Node {
    ImportKind kind{ImportKind::IMPORT_SINGLE};
    bool hasDoubleColon{};                /**< Has '::', i.e. orgnization name */
    /// Prefer to use GetPrefixPath() and GetImportedPackageName().
    std::vector<std::string> prefixPaths; /**< Prefix paths in packageName. */
    std::vector<Position> prefixPoses;    /**< Prefix positions in packageName. */
    std::vector<Position> prefixDotPoses; /**< Dot positions in packageName. */
    // Used for single-import, alias-import, all-import
    Identifier identifier; /**< Imported identifier. */
    // Used for alias-import
    Position asPos;           /**< Position of 'as'. */
    Identifier aliasName; /**< Alias identifier. */
    // Used for multi-import
    Position leftCurlPos;             /**< Position of '{'. */
    std::vector<ImportContent> items; /**< Multi-imported items. */
    std::vector<Position> commaPoses; /**< Positions of each ','. */
    Position rightCurlPos;            /**< Position of '}'. */
    bool isDecl{false};               /**< Identifier is a declaration, set by ImportManager. */
    ImportContent() : Node(ASTKind::IMPORT_CONTENT)
    {
    }
    std::string ToString() const override;
    std::string GetPrefixPath() const;
    std::string GetImportedPackageName() const;
};

/**
 * An ImportSpec represents an import sentence in file header.
 */
struct ImportSpec : Node {
    OwnedPtr<Modifier> modifier;
    Position importPos; /**< Position of 'import'. */
    ImportContent content;
    std::vector<OwnedPtr<Annotation>> annotations; /**< Annotation set of the ImportSpec. */
    ImportSpec() : Node(ASTKind::IMPORT_SPEC)
    {
    }

    bool IsReExport() const
    {
        return modifier && modifier->modifier != TokenKind::PRIVATE;
    }
    bool IsImportAll() const
    {
        return content.kind == ImportKind::IMPORT_ALL;
    }
    bool IsImportSingle() const
    {
        return content.kind == ImportKind::IMPORT_SINGLE;
    }
    bool IsImportAlias() const
    {
        return content.kind == ImportKind::IMPORT_ALIAS;
    }
    bool IsImportMulti() const
    {
        return content.kind == ImportKind::IMPORT_MULTI;
    }

    bool IsPrivateImport() const
    {
        return !modifier || modifier->modifier == TokenKind::PRIVATE;
    }
};

/**
 * A PackageSpec node represents the package of the current file.
 */
struct PackageSpec : Node {
    OwnedPtr<Modifier> modifier;
    Position macroPos;                    /**< Position of 'macro'. */
    Position packagePos;                  /**< Position of 'package'. */
    bool hasDoubleColon{};                /**< Has '::', i.e. orgnization name */
    // For the following three vectors, a valid `PackageSpec` should have the same size.
    /// Prefer to use GetPackageName().
    std::vector<std::string> prefixPaths; /**< Prefix paths in packageName. */
    std::vector<Position> prefixPoses;    /**< Prefix positions in packageName. */
    std::vector<Position> prefixDotPoses; /**< Dot positions in packageName. */
    Identifier packageName;               /**< Package name. */
    bool hasMacro{false};
    bool hasPlatform{false};
    bool hasCommon{false};
    PackageSpec() : Node(ASTKind::PACKAGE_SPEC)
    {
    }
    std::string GetPackageName() const;
};

/**
 * A File node represents one source file.
 */
struct File : Node {
    std::string fileName;                      /**< File name. Generated by parser */
    std::string filePath;                      /**< File path. Generated by parser */
    uint64_t fileHash{0};                      /**< Hash of the file. Generated by parser */
    OwnedPtr<FeaturesDirective> feature;      /**< Features that belong to file. Generated by parser, Optional */
    OwnedPtr<PackageSpec> package;             /**< The package the file belongs to. Generated by parser, Optional */
    std::vector<OwnedPtr<ImportSpec>> imports; /**< Import information. Generated by parser */
    std::vector<OwnedPtr<Decl>> decls;         /**< All toplevel decls. Generated by parser */
    std::vector<OwnedPtr<Node>> trashBin;
    Ptr<Package> curPackage{nullptr}; /**< Current package node. */
    size_t indexOfPackage;
    bool hasMacro{false};               /**< Whether has definition or call of macro. Generated by parser */
    std::string macroCallFilePath;      /**< MacroCall File path after macro expansion. */
    Position macroCallPosBase{0, 1, 1}; /**< MacroCall pos base for macro expansion. */
    std::vector<OwnedPtr<Node>> originalMacroCallNodes; /**< Owner of MacroCall ASTs after macro expansion. */
    std::vector<OwnedPtr<Decl>> exportedInternalDecls;  /**< Ptr to the exported internal declarations. */
    bool isCommon{false};
    bool isPlatform{false};
    File() : Node(ASTKind::FILE)
    {
    }
    bool operator==(const File& r) const
    {
        return fileName == r.fileName && filePath == r.filePath && fileHash == r.fileHash;
    }
    bool operator!=(const File& r) const
    {
        return !(*this == r);
    }
};

enum class AccessLevel {
    PRIVATE,
    INTERNAL,
    PROTECTED,
    PUBLIC,
};

/**
 * A Package Node represents a package contains multi files and imports.
 */
struct Package : Node {
    std::string fullPackageName{"default"};               /**< Package name, default name is 'default'. */
    std::vector<OwnedPtr<File>> files;                    /**< All src files in package. */
    std::vector<OwnedPtr<Decl>> genericInstantiatedDecls; /**< The instantiations of the generic decls. */
    /** Imported non-generic functions or global const variables with source code. */
    std::vector<Ptr<Decl>> srcImportedNonGenericDecls;
    // Following three members are used after sema.
    std::vector<Ptr<FuncDecl>> inlineFuncDecls; /**< Imported inline functions. */
    AccessLevel accessible{AccessLevel::PUBLIC};
    bool hasSourceImportedDecl{false};
    bool isMacroPackage{false};
    bool noSubPkg{false};
    bool needExported{true}; /**< Parent path of package path is "src", there is no need to export this package. */

    Package() : Node(ASTKind::PACKAGE)
    {
    }
    Package(const std::string& pkgName) : Node(ASTKind::PACKAGE), fullPackageName(pkgName)
    {
    }

    bool IsEmpty() const
    {
        for (auto& file : files) {
            if (file->package || !file->decls.empty()) {
                return false;
            }
            // Filter compiler added importSpec of core in stdlib.
            for (auto& import : file->imports) {
                if (!import->TestAttr(Attribute::COMPILER_ADD)) {
                    return false;
                }
            }
        }
        return true;
    }
    bool HasFeature() const
    {
        for (auto& file : files) {
            if (file->feature != nullptr && file->feature->content.size() > 0) {
                return true;
            }
        }
        return false;
    }
};

/**
 * A PackageDecl node represents imported package.
 */
struct PackageDecl : Decl {
    Ptr<Package> const srcPackage;                                 /**< Imported source package node. */
    PackageDecl(Package& pkg) : Decl(ASTKind::PACKAGE_DECL), srcPackage(&pkg)
    {
        identifier = pkg.fullPackageName;
        fullPackageName = pkg.fullPackageName;
        if (pkg.TestAttr(Attribute::IMPORTED)) {
            EnableAttr(Attribute::IMPORTED);
        }
    }
};

/**
 * A spawn expression node.
 */
struct SpawnExpr : Expr {
    Position spawnPos;           /**< The position of 'spawn'. Generated by parser */
    OwnedPtr<VarDecl> futureObj; /**< The future object that each spawn should created. */
    OwnedPtr<Expr> task;         /**< The task that should executed. Generated by parser */
    OwnedPtr<Expr> arg;          /**< The thread context argument. Generated by parser, Optional */
    Position leftParenPos;       /**< Position of '('. Optional */
    Position rightParenPos;      /**< Position of ')'. Optional */
    SpawnExpr() : Expr(ASTKind::SPAWN_EXPR)
    {
    }
};

/**
 * A spawn expression node.
 */
struct SynchronizedExpr : Expr {
    Position syncPos; /**< The position of 'synchronized'. */
    Position leftParenPos;
    OwnedPtr<Expr> mutex; /**< The mutex that the synchronized block referred. */
    Position rightParenPos;
    OwnedPtr<Block> body; /**< The block inside the Synchronized. */
    SynchronizedExpr() : Expr(ASTKind::SYNCHRONIZED_EXPR)
    {
    }
};

inline bool CompNodeByPos(Ptr<const AST::Node> n1, Ptr<const AST::Node> n2)
{
    if (!n1 || !n2) {
        return n1 < n2;
    }
    // 'n1' is less than 'n2' if 'n1' and 'n2' are not null and n1's position is less than n2's position.
    // Compare pointers if the node positions are same.
    // NOTE: comparison of Postion will ignore 'fileID', so compare fileID separately.
    return n1->begin.fileID < n2->begin.fileID || (n1->begin.fileID == n2->begin.fileID && n1->begin < n2->begin) ||
        (n1->begin.fileID == n2->begin.fileID && n1->begin == n2->begin && n1 < n2);
}

struct CmpNodeByPos {
    bool operator()(Ptr<const Node> n1, Ptr<const Node> n2) const
    {
        return CompNodeByPos(n1, n2);
    }
};
using OrderedDeclSet = std::set<Ptr<Decl>, CmpNodeByPos>;
} // namespace AST
} // namespace Cangjie

#endif // CANGJIE_AST_NODE_H
